8000 ports/mimxrt: Add machine.CAN driver. · micropython/micropython@1ba6ef5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 1ba6ef5

Browse files
committed
ports/mimxrt: Add machine.CAN driver.
Signed-off-by: Kwabena W. Agyeman <kwagyeman@live.com>
1 parent 1dedb65 commit 1ba6ef5

24 files changed

+1261
-1
lines changed

docs/library/machine.CAN.rst

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
.. currentmodule:: machine
2+
.. _machine.CAN:
3+
4+
class CAN -- controller area network communication bus
5+
======================================================
6+
7+
CAN implements support for classic CAN controllers.
8+
At the physical level CAN bus consists of 2 lines: RX and TX. Note that to connect the board to a
9+
CAN bus you must use a CAN transceiver to convert the CAN logic signals from the board to the correct
10+
voltage levels on the bus.
11+
12+
Example usage for classic CAN controller in Loopback (transceiver-less) mode::
13+
14+
from machine import CAN
15+
can = CAN(1, CAN.LOOPBACK)
16+
can.setfilter(0, CAN.LIST32, 0, (123, 124)) # set a filter to receive messages with id=123 and 124
17+
can.send('message!', 123) # send a message with id 123
18+
can.recv(0) # receive message on FIFO 0
19+
20+
The following CAN module functions and their arguments are available
21+
for classic CAN controllers, unless otherwise stated.
22+
23+
Availability: IMXRT.
24+
25+
Constructors
26+
------------
27+
28+
.. class:: CAN(bus, ...)
29+
30+
Construct a CAN object on the given bus. *bus* can be 1-3.
31+
With no additional parameters, the CAN object is created but not
32+
initialised (it has the settings from the last initialisation of
33+
the bus, if any). If extra arguments are given, the bus is initialised.
34+
See :meth:`CAN.init` for parameters of initialisation.
35+
36+
Methods
37+
-------
38+
39+
.. method:: CAN.init(mode, *, auto_restart=False, baudrate=0)
40+
41+
Initialise the CAN bus with the given parameters:
42+
43+
- *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
44+
- *auto_restart* sets whether the controller will automatically try and restart
45+
communications after entering the bus-off state; if this is disabled then
46+
:meth:`~CAN.restart()` can be used to leave the bus-off state
47+
- *baudrate* can be 33333, 50000, 62500, 83333, 100000, 125000, 250000, 500000, or 1000000.
48+
49+
.. method:: CAN.deinit()
50+
51+
Turn off the CAN bus.
52+
53+
.. method:: CAN.restart()
54+
55+
Force F438 a software restart of the CAN controller without resetting its
56+
configuration.
57+
58+
If the controller enters the bus-off state then it will no longer participate
59+
in bus activity. If the controller is not configured to automatically restart
60+
(see :meth:`~CAN.init()`) then this method can be used to trigger a restart,
61+
and the controller will follow the CAN protocol to leave the bus-off state and
62+
go into the error active state.
63+
64+
.. method:: CAN.state()
65+
66+
Return the state of the controller. The return value can be one of:
67+
68+
- ``CAN.STOPPED`` -- the controller is completely off and reset;
69+
- ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state
70+
(both TEC and REC are less than 96);
71+
- ``CAN.ERROR_WARNING`` -- the controller is on and in the Error Warning state
72+
(at least one of TEC or REC is 96 or greater);
73+
- ``CAN.ERROR_PASSIVE`` -- the controller is on and in the Error Passive state
74+
(at least one of TEC or REC is 128 or greater);
75+
- ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity
76+
(TEC overflowed beyond 255).
77+
78+
.. method:: CAN.info([list])
79+
80+
Get information about the controller's error states and TX and RX buffers.
81+
If *list* is provided then it should be a list object with at least 8 entries,
82+
which will be filled in with the information. Otherwise a new list will be
83+
created and filled in. In both cases the return value of the method is the
84+
populated list.
85+
86+
The values in the list are:
87+
88+
- TEC value
89+
- REC value
90+
- number of times the controller enterted the Error Warning state (wrapped
91+
around to 0 after 65535)
92+
- number of times the controller enterted the Error Passive state (wrapped
93+
around to 0 after 65535)
94+
- number of times the controller enterted the Bus Off state (wrapped
95+
around to 0 after 65535)
96+
- number of pending TX messages
97+
- number of pending RX messages on fifo 0
98+
- number of pending RX messages on fifo 1
99+
100+
.. method:: CAN.setfilter(bank, mode, fifo, params, *, rtr, extframe=False)
101+
102+
Configure a filter bank:
103+
104+
- *bank* is the classic CAN controller filter bank to configure.
105+
- *mode* is the mode the filter should operate in, see the tables below.
106+
- *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter.
107+
- *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument.
108+
109+
+-----------------------+---------------------------------------------------------+
110+
|*mode* |Contents of *params* array for classic CAN controller |
111+
+=======================+=========================================================+
112+
|CAN.LIST32 or CAN.DUAL |Two 32 bit ids that will be accepted |
113+
+-----------------------+---------------------------------------------------------+
114+
115+
- *rtr* For classic CAN controllers, this is an array of booleans that states if
116+
a filter should accept a remote transmission request message. If this argument
117+
is not given then it defaults to ``False`` for all entries. The length of the
118+
array depends on the *mode* argument.
119+
120+
+-----------------------+----------------------+
121+
|*mode* |length of *rtr* array |
122+
+=======================+======================+
123+
|CAN.LIST32 or CAN.DUAL |2 |
124+
+-----------------------+----------------------+
125+
126+
- *extframe* If True the frame will have an extended identifier (29 bits),
127+
otherwise a standard identifier (11 bits) is used.
128+
129+
130+
.. method:: CAN.clearfilter(bank)
131+
132+
Clear and disables a filter bank:
133+
134+
- *bank* is the classic CAN controller filter bank to clear.
135+
136+
.. method:: CAN.any(fifo)
137+
138+
Return ``True`` if any message waiting on the FIFO, else ``False``.
139+
140+
.. method:: CAN.recv(fifo, list=None, *, timeout=5000)
141+
142+
Receive data on the bus:
143+
144+
- *fifo* is an integer, which is the FIFO to receive on
145+
- *list* is an optional list object to be used as the return value
146+
- *timeout* is the timeout in milliseconds to wait for the receive.
147+
148+
Return value: A tuple containing five values.
149+
150+
- The id of the message.
151+
- A boolean that indicates if the message ID is standard or extended.
152+
- A boolean that indicates if the message is an RTR message.
153+
- The FMI (Filter Match Index) value.
154+
- An array containing the data.
155+
156+
If *list* is ``None`` then a new tuple will be allocated, as well as a new
157+
bytes object to contain the data (as the fifth element in the tuple).
158+
159+
If *list* is not ``None`` then it should be a list object with a least five
160+
elements. The fifth element should be a memoryview object which is created
161+
from either a bytearray or an array of type 'B' or 'b', and this array must
162+
have enough room for at least 8 bytes. The list object will then be
163+
populated with the first four return values above, and the memoryview object
164+
will be resized inplace to the size of the data and filled in with that data.
165+
The same list and memoryview objects can be reused in subsequent calls to
166+
this method, providing a way of receiving data without using the heap.
167+
For example::
168+
169+
buf = bytearray(8)
170+
lst = [0, 0, 0, 0, memoryview(buf)]
171+
# No heap memory is allocated in the following call
172+
can.recv(0, lst)
173+
174+
.. method:: CAN.send(data, id, *, timeout=0, rtr=False, extframe=False)
175+
176+
Send a message on the bus:
177+
178+
- *data* is the data to send (an integer to send, or a buffer object).
179+
- *id* is the id of the message to be sent.
180+
- *timeout* is the timeout in milliseconds to wait for the send.
181+
- *rtr* is a boolean that specifies if the message shall be sent as
182+
a remote transmission request. If *rtr* is True then only the length
183+
of *data* is used to fill in the DLC slot of the frame; the actual
184+
bytes in *data* are unused.
185+
- *extframe* if True the frame will have an extended identifier (29 bits),
186+
otherwise a standard identifier (11 bits) is used.
187+
188+
If timeout is 0 the message is placed in a buffer in one of three hardware
189+
buffers and the method returns immediately. If all three buffers are in use
190+
an exception is thrown. If timeout is not 0, the method waits until the
191+
message is transmitted. If the message can't be transmitted within the
192+
specified time an exception is thrown.
193+
194+
Return value: ``None``.
195+
196+
.. method:: CAN.rxcallback(fifo, fun)
197+
198+
Register a function to be called when a message is accepted into a empty fifo:
199+
200+
- *fifo* is the receiving fifo.
201+
- *fun* is the function to be called when the fifo becomes non empty.
202+
203+
The callback function takes two arguments the first is the can object it self the second is
204+
a integer that indicates the reason for the callback.
205+
206+
+--------+------------------------------------------------+
207+
| Reason | |
208+
+========+================================================+
209+
| 0 | A message has been accepted into a empty FIFO. |
210+
+--------+------------------------------------------------+
211+
| 1 | The FIFO is full |
212+
+--------+------------------------------------------------+
213+
| 2 | A message has been lost due to a full FIFO |
214+
+--------+------------------------------------------------+
215+
216+
Example use of rxcallback::
217+
218+
def cb0(bus, reason):
219+
print('cb0')
220+
if reason == 0:
221+
print('pending')
222+
if reason == 1:
223+
print('full')
224+
if reason == 2:
225+
print('overflow')
226+
227+
can = CAN(1, CAN.LOOPBACK)
228+
can.rxcallback(0, cb0)
229+
230+
Constants
231+
---------
232+
233+
.. data:: CAN.NORMAL
234+
CAN.LOOPBACK
235+
CAN.SILENT
236+
CAN.SILENT_LOOPBACK
237+
238+
The mode of the CAN bus used in :meth:`~CAN.init()`.
239+
240+
.. data:: CAN.STOPPED
241+
CAN.ERROR_ACTIVE
242+
CAN.ERROR_WARNING
243+
CAN.ERROR_PASSIVE
244+
CAN.BUS_OFF
245+
246+
Possible states of the CAN controller returned from :meth:`~CAN.state()`.
247+
248+
.. data:: CAN.LIST32
249+
CAN.DUAL
250+
251+
The operation mode of a filter used in :meth:`~CAN.setfilter()` for classic CAN.

docs/library/machine.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ Classes
255255
machine.Signal.rst
256256
machine.ADC.rst
257257
machine.ADCBlock.rst
258+
machine.CAN.rst
258259
machine.PWM.rst
259260
machine.UART.rst
260261
machine.SPI.rst

ports/mimxrt/Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ ifeq ($(MICROPY_PY_MACHINE_SDCARD),1)
156156
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_usdhc.c
157157
endif
158158

159+
ifeq ($(MICROPY_HW_ENABLE_CAN),1)
160+
SRC_HAL_IMX_C += $(MCU_DIR)/drivers/fsl_flexcan.c
161+
endif
162+
159163
ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES), MIMXRT1015 MIMXRT1021 MIMXRT1052 MIMXRT1062 MIMXRT1064 MIMXRT1176))
160164
SRC_HAL_IMX_C += \
161165
$(MCU_DIR)/drivers/fsl_qtmr.c \
@@ -195,6 +199,7 @@ SRC_C += \
195199
led.c \
196200
machine_adc.c \
197201
machine_bitstream.c \
202+
machine_can.c \
198203
machine_i2c.c \
199204
machine_i2s.c \
200205
machine_led.c \
@@ -323,6 +328,7 @@ endif
323328
MICROPY_HW_SDRAM_AVAIL ?= 0
324329
MICROPY_HW_SDRAM_SIZE ?= 0
325330
MICROPY_PY_MACHINE_SDCARD ?= 0
331+
MICROPY_HW_ENABLE_CAN ?= 0
326332

327333
# Configure default compiler flags
328334
CFLAGS += \
@@ -343,6 +349,7 @@ CFLAGS += \
343349
-DMICROPY_HW_SDRAM_AVAIL=$(MICROPY_HW_SDRAM_AVAIL) \
344350
-DMICROPY_HW_SDRAM_SIZE=$(MICROPY_HW_SDRAM_SIZE) \
345351
-DMICROPY_PY_MACHINE_SDCARD=$(MICROPY_PY_MACHINE_SDCARD) \
352+
-DMICROPY_HW_ENABLE_CAN=$(MICROPY_HW_ENABLE_CAN) \
346353
-DSPI_RETRY_TIMES=1000000 \
347354
-DUART_RETRY_TIMES=1000000 \
348355
-DXIP_BOOT_HEADER_ENABLE=1 \

ports/mimxrt/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ MIMXRT1064_EVK boards.
88
Features:
99
- REPL over USB VCP
1010
- machine.ADC
11+
- machine.CAN
1112
- machine.I2C
1213
- machine.LED
1314
- machine.Pin
@@ -27,7 +28,7 @@ Features:
2728
Known issues:
2829

2930
TODO:
30-
- More peripherals (Counter, I2S, CAN, etc)
31+
- More peripherals (Counter, I2S, etc)
3132
- More Python options
3233

3334
## Build Instructions

ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@
7777
{ 0 }, { 0 }, \
7878
{ IOMUXC_GPIO_SD_B1_02_LPI2C4_SCL }, { IOMUXC_GPIO_SD_B1_03_LPI2C4_SDA },
7979

80+
#define MICROPY_HW_CAN_INDEX { 1 }
81+
#define MICROPY_HW_NUM_CAN_IRQS (1)
82+
83+
#define IOMUX_TABLE_CAN \
84+
{ IOMUXC_GPIO_SD_B1_00_FLEXCAN1_TX }, { IOMUXC_GPIO_SD_B1_01_FLEXCAN1_RX },
85+
8086
#define MICROPY_PY_MACHINE_I2S (1)
8187
#define MICROPY_HW_I2S_NUM (1)
8288
#define I2S_CLOCK_MUX { 0, kCLOCK_Sai1Mux, kCLOCK_Sai2Mux }

ports/mimxrt/boards/MIMXRT1020_EVK/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ MCU_VARIANT = MIMXRT1021DAG5A
33

44
MICROPY_FLOAT_IMPL = double
55
MICROPY_PY_MACHINE_SDCARD = 1
6+
MICROPY_HW_ENABLE_CAN = 1
67
MICROPY_HW_FLASH_TYPE = qspi_nor_flash
78
MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
89

ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@
6565
{ 0 }, { 0 }, \
6666
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
6767

68+
#define MICROPY_HW_CAN_INDEX { 2 }
69+
#define MICROPY_HW_NUM_CAN_IRQS (1)
70+
71+
#define IOMUX_TABLE_CAN \
72+
{ 0 }, { 0 }, \
73+
{ IOMUXC_GPIO_AD_B0_14_FLEXCAN2_TX }, { IOMUXC_GPIO_AD_B0_15_FLEXCAN2_RX },
74+
6875
#define MICROPY_PY_MACHINE_I2S (1)
6976
#define MICROPY_HW_I2S_NUM (1)
7077
#define I2S_CLOCK_MUX { 0, kCLOCK_Sai1Mux, kCLOCK_Sai2Mux }

ports/mimxrt/boards/MIMXRT1050_EVK/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ MCU_VARIANT = MIMXRT1052DVL6B
33

44
MICROPY_FLOAT_IMPL = double
55
MICROPY_PY_MACHINE_SDCARD = 1
6+
MICROPY_HW_ENABLE_CAN = 1
67
MICROPY_HW_FLASH_TYPE = qspi_hyper_flash
78
MICROPY_HW_FLASH_SIZE = 0x4000000 # 64MB
89

ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@
6565
{ 0 }, { 0 }, \
6666
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
6767

68+
#define MICROPY_HW_CAN_INDEX { 2 }
69+
#define MICROPY_HW_NUM_CAN_IRQS (1)
70+
71+
#define IOMUX_TABLE_CAN \
72+
{ 0 }, { 0 }, \
73+
{ IOMUXC_GPIO_AD_B0_14_FLEXCAN2_TX }, { IOMUXC_GPIO_AD_B0_15_FLEXCAN2_RX },
74+
6875
#define MICROPY_PY_MACHINE_I2S (1)
6976
#define MICROPY_HW_I2S_NUM (1)
7077
#define I2S_CLOCK_MUX { 0, kCLOCK_Sai1Mux, kCLOCK_Sai2Mux }

ports/mimxrt/boards/MIMXRT1060_EVK/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ MCU_VARIANT = MIMXRT1062DVJ6A
33

44
MICROPY_FLOAT_IMPL = double
55
MICROPY_PY_MACHINE_SDCARD = 1
6+
MICROPY_HW_ENABLE_CAN = 1
67
MICROPY_HW_FLASH_TYPE = qspi_nor_flash
78
MICROPY_HW_FLASH_SIZE = 0x800000 # 8MB
89

ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@
6565
{ 0 }, { 0 }, \
6666
{ IOMUXC_GPIO_AD_B1_07_LPI2C3_SCL }, { IOMUXC_GPIO_AD_B1_06_LPI2C3_SDA },
6767

68+
#define MICROPY_HW_CAN_INDEX { 2 }
69+
#define MICROPY_HW_NUM_CAN_IRQS (1)
70+
71+
#define IOMUX_TABLE_CAN \
72+
{ 0 }, { 0 }, \
73+
{ IOMUXC_GPIO_AD_B0_14_FLEXCAN2_TX }, { IOMUXC_GPIO_AD_B0_15_FLEXCAN2_RX },
74+
6875
#define MICROPY_PY_MACHINE_I2S (1)
6976
#define MICROPY_HW_I2S_NUM (1)
7077
#define I2S_CLOCK_MUX { 0, kCLOCK_Sai1Mux, kCLOCK_Sai2Mux }

ports/mimxrt/boards/MIMXRT1064_EVK/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ MCU_VARIANT = MIMXRT1064DVL6A
33

44
MICROPY_FLOAT_IMPL = double
55
MICROPY_PY_MACHINE_SDCARD = 1
6+
MICROPY_HW_ENABLE_CAN = 1
67
MICROPY_HW_FLASH_TYPE = internal
78
MICROPY_HW_FLASH_SIZE = 0x400000 # 4MB
89

0 commit comments

Comments
 (0)
0