Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
7d5e3428
Commit
7d5e3428
authored
Apr 16, 2015
by
Damien George
Browse files
stmhal: Allow sending CAN messages with timeout=0.
Thanks to Henrik Sölver for this patch.
parent
4c459213
Changes
4
Hide whitespace changes
Inline
Side-by-side
docs/library/pyb.CAN.rst
View file @
7d5e3428
...
...
@@ -126,7 +126,7 @@ Methods
Return value: buffer of data bytes.
.. method:: can.send(send, addr, \*, timeout=
500
0)
.. method:: can.send(send, addr, \*, timeout=0)
Send a message on the bus:
...
...
@@ -134,6 +134,12 @@ Methods
- ``addr`` is the address to send to
- ``timeout`` is the timeout in milliseconds to wait for the send.
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
an exception is thrown. If timeout is not 0, the method waits until the
message is transmitted. If the message can't be transmitted within the
specified time an exception is thrown.
Return value: ``None``.
.. method:: can.rxcallback(fifo, fun)
...
...
stmhal/can.c
View file @
7d5e3428
...
...
@@ -170,6 +170,96 @@ STATIC void can_clearfilter(uint32_t f) {
HAL_CAN_ConfigFilter
(
NULL
,
&
filter
);
}
// We have our own version of CAN transmit so we can handle Timeout=0 correctly.
STATIC
HAL_StatusTypeDef
CAN_Transmit
(
CAN_HandleTypeDef
*
hcan
,
uint32_t
Timeout
)
{
uint32_t
transmitmailbox
;
uint32_t
tickstart
;
uint32_t
rqcpflag
;
uint32_t
txokflag
;
// Check the parameters
assert_param
(
IS_CAN_IDTYPE
(
hcan
->
pTxMsg
->
IDE
));
assert_param
(
IS_CAN_RTR
(
hcan
->
pTxMsg
->
RTR
));
assert_param
(
IS_CAN_DLC
(
hcan
->
pTxMsg
->
DLC
));
// Select one empty transmit mailbox
if
((
hcan
->
Instance
->
TSR
&
CAN_TSR_TME0
)
==
CAN_TSR_TME0
)
{
transmitmailbox
=
CAN_TXMAILBOX_0
;
rqcpflag
=
CAN_FLAG_RQCP0
;
txokflag
=
CAN_FLAG_TXOK0
;
}
else
if
((
hcan
->
Instance
->
TSR
&
CAN_TSR_TME1
)
==
CAN_TSR_TME1
)
{
transmitmailbox
=
CAN_TXMAILBOX_1
;
rqcpflag
=
CAN_FLAG_RQCP1
;
txokflag
=
CAN_FLAG_TXOK1
;
}
else
if
((
hcan
->
Instance
->
TSR
&
CAN_TSR_TME2
)
==
CAN_TSR_TME2
)
{
transmitmailbox
=
CAN_TXMAILBOX_2
;
rqcpflag
=
CAN_FLAG_RQCP2
;
txokflag
=
CAN_FLAG_TXOK2
;
}
else
{
transmitmailbox
=
CAN_TXSTATUS_NOMAILBOX
;
}
if
(
transmitmailbox
!=
CAN_TXSTATUS_NOMAILBOX
)
{
// Set up the Id
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TIR
&=
CAN_TI0R_TXRQ
;
if
(
hcan
->
pTxMsg
->
IDE
==
CAN_ID_STD
)
{
assert_param
(
IS_CAN_STDID
(
hcan
->
pTxMsg
->
StdId
));
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TIR
|=
((
hcan
->
pTxMsg
->
StdId
<<
21
)
|
\
hcan
->
pTxMsg
->
RTR
);
}
else
{
assert_param
(
IS_CAN_EXTID
(
hcan
->
pTxMsg
->
ExtId
));
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TIR
|=
((
hcan
->
pTxMsg
->
ExtId
<<
3
)
|
\
hcan
->
pTxMsg
->
IDE
|
\
hcan
->
pTxMsg
->
RTR
);
}
// Set up the DLC
hcan
->
pTxMsg
->
DLC
&=
(
uint8_t
)
0x0000000F
;
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TDTR
&=
(
uint32_t
)
0xFFFFFFF0
;
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TDTR
|=
hcan
->
pTxMsg
->
DLC
;
// Set up the data field
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TDLR
=
(((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
3
]
<<
24
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
2
]
<<
16
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
1
]
<<
8
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
0
]));
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TDHR
=
(((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
7
]
<<
24
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
6
]
<<
16
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
5
]
<<
8
)
|
((
uint32_t
)
hcan
->
pTxMsg
->
Data
[
4
]));
// Request transmission
hcan
->
Instance
->
sTxMailBox
[
transmitmailbox
].
TIR
|=
CAN_TI0R_TXRQ
;
if
(
Timeout
==
0
)
{
return
HAL_OK
;
}
// Get tick
tickstart
=
HAL_GetTick
();
// Check End of transmission flag
while
(
!
(
__HAL_CAN_TRANSMIT_STATUS
(
hcan
,
transmitmailbox
)))
{
// Check for the Timeout
if
(
Timeout
!=
HAL_MAX_DELAY
)
{
if
((
HAL_GetTick
()
-
tickstart
)
>
Timeout
)
{
// When the timeout expires, we try to abort the transmission of the packet
__HAL_CAN_CANCEL_TRANSMIT
(
hcan
,
transmitmailbox
);
while
(
!
__HAL_CAN_GET_FLAG
(
hcan
,
rqcpflag
))
{
}
if
(
__HAL_CAN_GET_FLAG
(
hcan
,
txokflag
))
{
// The abort attempt failed and the message was sent properly
return
HAL_OK
;
}
else
{
return
HAL_TIMEOUT
;
}
}
}
}
return
HAL_OK
;
}
else
{
return
HAL_BUSY
;
}
}
/******************************************************************************/
// Micro Python bindings
...
...
@@ -348,7 +438,7 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
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_timeout
,
MP_ARG_KW_ONLY
|
MP_ARG_INT
,
{.
u_int
=
500
0
}
},
{
MP_QSTR_timeout
,
MP_ARG_KW_ONLY
|
MP_ARG_INT
,
{.
u_int
=
0
}
},
};
// parse args
...
...
@@ -380,7 +470,7 @@ STATIC mp_obj_t pyb_can_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
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
=
HAL_
CAN_Transmit
(
&
self
->
can
,
args
[
2
].
u_int
);
HAL_StatusTypeDef
status
=
CAN_Transmit
(
&
self
->
can
,
args
[
2
].
u_int
);
if
(
status
!=
HAL_OK
)
{
mp_hal_raise
(
status
);
...
...
tests/pyb/can.py
View file @
7d5e3428
from
pyb
import
CAN
import
pyb
CAN
.
initfilterbanks
(
14
)
can
=
CAN
(
1
)
...
...
@@ -11,19 +12,19 @@ print(can.any(0))
# Catch all filter
can
.
setfilter
(
0
,
CAN
.
MASK16
,
0
,
(
0
,
0
,
0
,
0
))
can
.
send
(
'abcd'
,
123
)
can
.
send
(
'abcd'
,
123
,
timeout
=
5000
)
print
(
can
.
any
(
0
))
print
(
can
.
recv
(
0
))
can
.
send
(
'abcd'
,
-
1
)
can
.
send
(
'abcd'
,
-
1
,
timeout
=
5000
)
print
(
can
.
recv
(
0
))
can
.
send
(
'abcd'
,
0x7FF
+
1
)
can
.
send
(
'abcd'
,
0x7FF
+
1
,
timeout
=
5000
)
print
(
can
.
recv
(
0
))
# Test too long message
try
:
can
.
send
(
'abcdefghi'
,
0x7FF
)
can
.
send
(
'abcdefghi'
,
0x7FF
,
timeout
=
5000
)
except
ValueError
:
print
(
'passed'
)
else
:
...
...
@@ -39,7 +40,7 @@ can.setfilter(0, CAN.MASK32, 0, (0, 0))
print
(
can
)
try
:
can
.
send
(
'abcde'
,
0x7FF
+
1
)
can
.
send
(
'abcde'
,
0x7FF
+
1
,
timeout
=
5000
)
except
ValueError
:
print
(
'failed'
)
else
:
...
...
@@ -95,17 +96,17 @@ def cb1a(bus, reason):
can
.
rxcallback
(
0
,
cb0
)
can
.
rxcallback
(
1
,
cb1
)
can
.
send
(
'11111111'
,
1
)
can
.
send
(
'22222222'
,
2
)
can
.
send
(
'33333333'
,
3
)
can
.
send
(
'11111111'
,
1
,
timeout
=
5000
)
can
.
send
(
'22222222'
,
2
,
timeout
=
5000
)
can
.
send
(
'33333333'
,
3
,
timeout
=
5000
)
can
.
rxcallback
(
0
,
cb0a
)
can
.
send
(
'44444444'
,
4
)
can
.
send
(
'44444444'
,
4
,
timeout
=
5000
)
can
.
send
(
'55555555'
,
5
)
can
.
send
(
'66666666'
,
6
)
can
.
send
(
'77777777'
,
7
)
can
.
send
(
'55555555'
,
5
,
timeout
=
5000
)
can
.
send
(
'66666666'
,
6
,
timeout
=
5000
)
can
.
send
(
'77777777'
,
7
,
timeout
=
5000
)
can
.
rxcallback
(
1
,
cb1a
)
can
.
send
(
'88888888'
,
8
)
can
.
send
(
'88888888'
,
8
,
timeout
=
5000
)
print
(
can
.
recv
(
0
))
print
(
can
.
recv
(
0
))
...
...
@@ -114,9 +115,39 @@ print(can.recv(1))
print
(
can
.
recv
(
1
))
print
(
can
.
recv
(
1
))
can
.
send
(
'11111111'
,
1
)
can
.
send
(
'55555555'
,
5
)
can
.
send
(
'11111111'
,
1
,
timeout
=
5000
)
can
.
send
(
'55555555'
,
5
,
timeout
=
5000
)
print
(
can
.
recv
(
0
))
print
(
can
.
recv
(
1
))
del
can
# Testing asyncronous send
can
=
CAN
(
1
,
CAN
.
LOOPBACK
)
can
.
setfilter
(
0
,
CAN
.
MASK16
,
0
,
(
0
,
0
,
0
,
0
))
while
can
.
any
(
0
):
can
.
recv
(
0
)
can
.
send
(
'abcde'
,
1
,
timeout
=
0
)
print
(
can
.
any
(
0
))
while
not
can
.
any
(
0
):
pass
print
(
can
.
recv
(
0
))
try
:
can
.
send
(
'abcde'
,
2
,
timeout
=
0
)
can
.
send
(
'abcde'
,
3
,
timeout
=
0
)
can
.
send
(
'abcde'
,
4
,
timeout
=
0
)
can
.
send
(
'abcde'
,
5
,
timeout
=
0
)
except
OSError
as
e
:
if
str
(
e
)
==
'16'
:
print
(
'passed'
)
else
:
print
(
'failed'
)
pyb
.
delay
(
500
)
while
can
.
any
(
0
):
print
(
can
.
recv
(
0
))
tests/pyb/can.py.exp
View file @
7d5e3428
...
...
@@ -32,3 +32,9 @@ cb1a
pending
(1, 0, 0, b'11111111')
(5, 0, 0, b'55555555')
False
(1, 0, 0, b'abcde')
passed
(2, 0, 0, b'abcde')
(3, 0, 0, b'abcde')
(4, 0, 0, b'abcde')
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment