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

File tree

24 files changed

+1261
-1
lines changed

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 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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy