stmhal: Add support for sending and receiving CAN RTR messages.
This commit is contained in:
parent
259eaab9a9
commit
e3cd154317
@ -82,7 +82,7 @@ Methods
|
||||
|
||||
Turn off the CAN bus.
|
||||
|
||||
.. method:: can.setfilter(bank, mode, fifo, params)
|
||||
.. method:: can.setfilter(bank, mode, fifo, params, \*, rtr)
|
||||
|
||||
Configure a filter bank:
|
||||
|
||||
@ -107,6 +107,23 @@ Methods
|
||||
|CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.|
|
||||
+-----------+---------------------------------------------------------+
|
||||
|
||||
- ``rtr`` is an array of booleans that states if a filter should accept a
|
||||
remote transmission request message. If this argument is not given
|
||||
then it defaults to False for all entries. The length of the array
|
||||
depends on the ``mode`` argument.
|
||||
|
||||
+-----------+----------------------+
|
||||
|``mode`` |length of rtr array |
|
||||
+===========+======================+
|
||||
|CAN.LIST16 |4 |
|
||||
+-----------+----------------------+
|
||||
|CAN.LIST32 |2 |
|
||||
+-----------+----------------------+
|
||||
|CAN.MASK16 |2 |
|
||||
+-----------+----------------------+
|
||||
|CAN.MASK32 |1 |
|
||||
+-----------+----------------------+
|
||||
|
||||
.. method:: can.clearfilter(bank)
|
||||
|
||||
Clear and disables a filter bank:
|
||||
@ -124,15 +141,24 @@ Methods
|
||||
- ``fifo`` is an integer, which is the FIFO to receive on
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: buffer of data bytes.
|
||||
Return value: A tuple containing four values.
|
||||
|
||||
.. method:: can.send(send, addr, \*, timeout=0)
|
||||
- The id of the message.
|
||||
- A boolean that indicates if the message is an RTR message.
|
||||
- The FMI (Filter Match Index) value.
|
||||
- An array containing the data.
|
||||
|
||||
.. method:: can.send(data, id, \*, timeout=0, rtr=False)
|
||||
|
||||
Send a message on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``addr`` is the address to send to
|
||||
- ``data`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``id`` is the id of the message to be sent.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
- ``rtr`` is a boolean that specifies if the message shall be sent as
|
||||
a remote transmission request. If ``rtr`` is True then only the length
|
||||
of ``data`` is used to fill in the DLC slot of the frame; the actual
|
||||
bytes in ``data`` are unused.
|
||||
|
||||
If timeout is 0 the message is placed in a buffer in one of three hardware
|
||||
buffers and the method returns immediately. If all three buffers are in use
|
||||
|
81
stmhal/can.c
81
stmhal/can.c
@ -436,9 +436,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_can_any_obj, pyb_can_any);
|
||||
/// Return value: `None`.
|
||||
STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
@ -464,11 +465,16 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
tx_msg.StdId = args[1].u_int & 0x7FF;
|
||||
tx_msg.IDE = CAN_ID_STD;
|
||||
}
|
||||
tx_msg.RTR = CAN_RTR_DATA;
|
||||
if (args[3].u_bool == false) {
|
||||
tx_msg.RTR = CAN_RTR_DATA;
|
||||
} else {
|
||||
tx_msg.RTR = CAN_RTR_REMOTE;
|
||||
}
|
||||
tx_msg.DLC = bufinfo.len;
|
||||
for (mp_uint_t i = 0; i < bufinfo.len; i++) {
|
||||
tx_msg.Data[i] = ((byte*)bufinfo.buf)[i]; // Data is uint32_t but holds only 1 byte
|
||||
}
|
||||
|
||||
self->can.pTxMsg = &tx_msg;
|
||||
HAL_StatusTypeDef status = CAN_Transmit(&self->can, args[2].u_int);
|
||||
|
||||
@ -543,7 +549,7 @@ STATIC mp_obj_t pyb_can_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
} else {
|
||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(rx_msg.ExtId);
|
||||
}
|
||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(rx_msg.RTR);
|
||||
tuple->items[1] = rx_msg.RTR == CAN_RTR_REMOTE ? mp_const_true : mp_const_false;
|
||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(rx_msg.FMI);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, rx_msg.DLC);
|
||||
@ -597,6 +603,7 @@ STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_fifo, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_FILTER_FIFO0} },
|
||||
{ MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
@ -605,8 +612,14 @@ STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_uint_t len;
|
||||
mp_uint_t rtr_len;
|
||||
mp_uint_t rtr_masks[4] = {0, 0, 0, 0};
|
||||
mp_obj_t *rtr_flags;
|
||||
mp_obj_t *params;
|
||||
mp_obj_get_array(args[3].u_obj, &len, ¶ms);
|
||||
if (args[4].u_obj != MP_OBJ_NULL){
|
||||
mp_obj_get_array(args[4].u_obj, &rtr_len, &rtr_flags);
|
||||
}
|
||||
|
||||
CAN_FilterConfTypeDef filter;
|
||||
if (args[1].u_int == MASK16 || args[1].u_int == LIST16) {
|
||||
@ -615,15 +628,41 @@ STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
}
|
||||
filter.FilterScale = CAN_FILTERSCALE_16BIT;
|
||||
if (self->extframe) {
|
||||
filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])); // id1
|
||||
filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])); // mask1
|
||||
filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])); // id2
|
||||
filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])); // mask2
|
||||
} else {
|
||||
filter.FilterIdLow = mp_obj_get_int(params[0]) << 5; // id1
|
||||
filter.FilterMaskIdLow = mp_obj_get_int(params[1]) << 5; // mask1
|
||||
filter.FilterIdHigh = mp_obj_get_int(params[2]) << 5; // id2
|
||||
filter.FilterMaskIdHigh = mp_obj_get_int(params[3]) << 5; // mask2
|
||||
if (args[4].u_obj != MP_OBJ_NULL) {
|
||||
if (args[1].u_int == MASK16) {
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
||||
rtr_masks[1] = 0x02;
|
||||
rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
|
||||
rtr_masks[3] = 0x02;
|
||||
} else { // LIST16
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
||||
rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
|
||||
rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x02 : 0;
|
||||
rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x02 : 0;
|
||||
}
|
||||
}
|
||||
filter.FilterIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[0])) | rtr_masks[0]; // id1
|
||||
filter.FilterMaskIdLow = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[1])) | rtr_masks[1]; // mask1
|
||||
filter.FilterIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[2])) | rtr_masks[2]; // id2
|
||||
filter.FilterMaskIdHigh = EXTENDED_ID_TO_16BIT_FILTER(mp_obj_get_int(params[3])) | rtr_masks[3]; // mask2
|
||||
} else { // Basic frames
|
||||
if (args[4].u_obj != MP_OBJ_NULL) {
|
||||
if (args[1].u_int == MASK16) {
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0;
|
||||
rtr_masks[1] = 0x10;
|
||||
rtr_masks[2] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0;
|
||||
rtr_masks[3] = 0x10;
|
||||
} else { // LIST16
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x10 : 0;
|
||||
rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x10 : 0;
|
||||
rtr_masks[2] = mp_obj_get_int(rtr_flags[2]) ? 0x10 : 0;
|
||||
rtr_masks[3] = mp_obj_get_int(rtr_flags[3]) ? 0x10 : 0;
|
||||
}
|
||||
}
|
||||
filter.FilterIdLow = (mp_obj_get_int(params[0]) << 5) | rtr_masks[0]; // id1
|
||||
filter.FilterMaskIdLow = (mp_obj_get_int(params[1]) << 5) | rtr_masks[1]; // mask1
|
||||
filter.FilterIdHigh = (mp_obj_get_int(params[2]) << 5) | rtr_masks[2]; // id2
|
||||
filter.FilterMaskIdHigh = (mp_obj_get_int(params[3]) << 5) | rtr_masks[3]; // mask2
|
||||
}
|
||||
if (args[1].u_int == MASK16) {
|
||||
filter.FilterMode = CAN_FILTERMODE_IDMASK;
|
||||
@ -636,12 +675,20 @@ STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
if (len != 2) {
|
||||
goto error;
|
||||
}
|
||||
filter.FilterScale = CAN_FILTERSCALE_32BIT;
|
||||
|
||||
filter.FilterScale = CAN_FILTERSCALE_32BIT;
|
||||
if (args[4].u_obj != MP_OBJ_NULL) {
|
||||
if (args[1].u_int == MASK32) {
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
||||
rtr_masks[1] = 0x02;
|
||||
} else { // LIST32
|
||||
rtr_masks[0] = mp_obj_get_int(rtr_flags[0]) ? 0x02 : 0;
|
||||
rtr_masks[1] = mp_obj_get_int(rtr_flags[1]) ? 0x02 : 0;
|
||||
}
|
||||
}
|
||||
filter.FilterIdHigh = (mp_obj_get_int(params[0]) & 0xFF00) >> 13;
|
||||
filter.FilterIdLow = ((mp_obj_get_int(params[0]) & 0x00FF) << 3) | 4;
|
||||
filter.FilterIdLow = (((mp_obj_get_int(params[0]) & 0x00FF) << 3) | 4) | rtr_masks[0];
|
||||
filter.FilterMaskIdHigh = (mp_obj_get_int(params[1]) & 0xFF00 ) >> 13;
|
||||
filter.FilterMaskIdLow = ((mp_obj_get_int(params[1]) & 0x00FF) << 3) | 4;
|
||||
filter.FilterMaskIdLow = (((mp_obj_get_int(params[1]) & 0x00FF) << 3) | 4) | rtr_masks[1];
|
||||
if (args[1].u_int == MASK32) {
|
||||
filter.FilterMode = CAN_FILTERMODE_IDMASK;
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ Q(initfilterbanks)
|
||||
Q(clearfilter)
|
||||
Q(setfilter)
|
||||
Q(rxcallback)
|
||||
Q(rtr)
|
||||
Q(NORMAL)
|
||||
Q(LOOPBACK)
|
||||
Q(SILENT)
|
||||
|
@ -151,3 +151,40 @@ except OSError as e:
|
||||
pyb.delay(500)
|
||||
while can.any(0):
|
||||
print(can.recv(0))
|
||||
|
||||
# Testing rtr messages
|
||||
bus1 = CAN(1, CAN.LOOPBACK)
|
||||
bus2 = CAN(2, CAN.LOOPBACK, extframe = True)
|
||||
while bus1.any(0):
|
||||
bus1.recv(0)
|
||||
while bus2.any(0):
|
||||
bus2.recv(0)
|
||||
bus1.setfilter(0, CAN.LIST16, 0, (1, 2, 3, 4))
|
||||
bus1.setfilter(1, CAN.LIST16, 0, (5, 6, 7, 8), rtr=(True, True, True, True))
|
||||
bus1.setfilter(2, CAN.MASK16, 0, (64, 64, 32, 32), rtr=(False, True))
|
||||
bus2.setfilter(0, CAN.LIST32, 0, (1, 2), rtr=(True, True))
|
||||
bus2.setfilter(1, CAN.LIST32, 0, (3, 4), rtr=(True, False))
|
||||
bus2.setfilter(2, CAN.MASK32, 0, (16, 16), rtr=(False,))
|
||||
bus2.setfilter(2, CAN.MASK32, 0, (32, 32), rtr=(True,))
|
||||
|
||||
bus1.send('',1,rtr=True)
|
||||
print(bus1.any(0))
|
||||
bus1.send('',5,rtr=True)
|
||||
print(bus1.recv(0))
|
||||
bus1.send('',6,rtr=True)
|
||||
print(bus1.recv(0))
|
||||
bus1.send('',7,rtr=True)
|
||||
print(bus1.recv(0))
|
||||
bus1.send('',16,rtr=True)
|
||||
print(bus1.any(0))
|
||||
bus1.send('',32,rtr=True)
|
||||
print(bus1.recv(0))
|
||||
|
||||
bus2.send('',1,rtr=True)
|
||||
print(bus2.recv(0))
|
||||
bus2.send('',2,rtr=True)
|
||||
print(bus2.recv(0))
|
||||
bus2.send('',3,rtr=True)
|
||||
print(bus2.recv(0))
|
||||
bus2.send('',4,rtr=True)
|
||||
print(bus2.any(0))
|
||||
|
@ -2,9 +2,9 @@ CAN(1)
|
||||
CAN(1, CAN.LOOPBACK, extframe=False)
|
||||
False
|
||||
True
|
||||
(123, 0, 0, b'abcd')
|
||||
(2047, 0, 0, b'abcd')
|
||||
(0, 0, 0, b'abcd')
|
||||
(123, False, 0, b'abcd')
|
||||
(2047, False, 0, b'abcd')
|
||||
(0, False, 0, b'abcd')
|
||||
passed
|
||||
CAN(1, CAN.LOOPBACK, extframe=True)
|
||||
passed
|
||||
@ -20,21 +20,31 @@ cb1
|
||||
full
|
||||
cb1a
|
||||
overflow
|
||||
(1, 0, 0, b'11111111')
|
||||
(2, 0, 1, b'22222222')
|
||||
(4, 0, 3, b'44444444')
|
||||
(5, 0, 0, b'55555555')
|
||||
(6, 0, 1, b'66666666')
|
||||
(8, 0, 3, b'88888888')
|
||||
(1, False, 0, b'11111111')
|
||||
(2, False, 1, b'22222222')
|
||||
(4, False, 3, b'44444444')
|
||||
(5, False, 0, b'55555555')
|
||||
(6, False, 1, b'66666666')
|
||||
(8, False, 3, b'88888888')
|
||||
cb0a
|
||||
pending
|
||||
cb1a
|
||||
pending
|
||||
(1, 0, 0, b'11111111')
|
||||
(5, 0, 0, b'55555555')
|
||||
(1, False, 0, b'11111111')
|
||||
(5, False, 0, b'55555555')
|
||||
False
|
||||
(1, 0, 0, b'abcde')
|
||||
(1, False, 0, b'abcde')
|
||||
passed
|
||||
(2, 0, 0, b'abcde')
|
||||
(3, 0, 0, b'abcde')
|
||||
(4, 0, 0, b'abcde')
|
||||
(2, False, 0, b'abcde')
|
||||
(3, False, 0, b'abcde')
|
||||
(4, False, 0, b'abcde')
|
||||
False
|
||||
(5, True, 4, b'')
|
||||
(6, True, 5, b'')
|
||||
(7, True, 6, b'')
|
||||
False
|
||||
(32, True, 9, b'')
|
||||
(1, True, 0, b'')
|
||||
(2, True, 1, b'')
|
||||
(3, True, 2, b'')
|
||||
False
|
||||
|
Loading…
Reference in New Issue
Block a user