forked from micropython/micropython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcan.h
More file actions
209 lines (163 loc) · 7.61 KB
/
can.h
File metadata and controls
209 lines (163 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_STM32_CAN_H
#define MICROPY_INCLUDED_STM32_CAN_H
#include "py/mphal.h"
#if MICROPY_HW_ENABLE_CAN
// This API provides a higher abstraction layer over the two STM32
// CAN controller APIs provided by the ST HAL (one for their classic
// CAN controller, one for their FD CAN controller.)
// There are two implementations, can.c and fdcan.c - only one is included in
// the build for a given board.
#define PYB_CAN_1 (1)
#define PYB_CAN_2 (2)
#define PYB_CAN_3 (3)
#define MASK16 (0)
#define LIST16 (1)
#define MASK32 (2)
#define LIST32 (3)
#if MICROPY_HW_ENABLE_FDCAN
// Interface compatibility for the classic CAN controller HAL
#define CAN_TypeDef FDCAN_GlobalTypeDef
#define CAN_HandleTypeDef FDCAN_HandleTypeDef
#define CanTxMsgTypeDef FDCAN_TxHeaderTypeDef
#define CanRxMsgTypeDef FDCAN_RxHeaderTypeDef
#define CAN_MODE_NORMAL FDCAN_MODE_NORMAL
#define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK
#define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING
#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK
// FDCAN peripheral has independent indexes for standard id vs extended id filters
#if defined(STM32G4)
#define CAN_HW_MAX_STD_FILTER 28
#define CAN_HW_MAX_EXT_FILTER 8
#elif defined(STM32H7)
// The RAM filtering section is configured for 64 x 1 word elements for 11-bit standard
// identifiers, and 31 x 2 words elements for 29-bit extended identifiers.
// The total number of words reserved for the filtering per FDCAN instance is 126 words.
#define CAN_HW_MAX_STD_FILTER 64
#define CAN_HW_MAX_EXT_FILTER 31
#endif
// Value reported via machine.CAN.FILTER_MAX, somewhat optimistic as requires using
// the exact numbers of each type of filter.
#define CAN_HW_MAX_FILTER (CAN_HW_MAX_STD_FILTER + CAN_HW_MAX_EXT_FILTER)
#else
// CAN1 & CAN2 have 28 filters which can be arbitrarily split, but machine.CAN
// implementation hard-codes to 14/14. CAN3 has 14 independent filters.
#define CAN_HW_MAX_FILTER 14
#endif
typedef enum {
CAN_STATE_STOPPED,
CAN_STATE_ERROR_ACTIVE,
CAN_STATE_ERROR_WARNING,
CAN_STATE_ERROR_PASSIVE,
CAN_STATE_BUS_OFF,
} can_state_t;
typedef enum _rx_state_t {
RX_STATE_FIFO_EMPTY = 0,
RX_STATE_MESSAGE_PENDING,
RX_STATE_FIFO_FULL,
RX_STATE_FIFO_OVERFLOW,
} rx_state_t;
typedef enum {
CAN_INT_MESSAGE_RECEIVED,
CAN_INT_FIFO_FULL,
CAN_INT_FIFO_OVERFLOW, // These first 3 correspond to pyb.CAN.rxcallback args
CAN_INT_ERR_BUS_OFF,
CAN_INT_ERR_PASSIVE,
CAN_INT_ERR_WARNING,
CAN_INT_TX_COMPLETE,
} can_int_t;
typedef enum {
CAN_TX_FIFO,
CAN_TX_QUEUE,
} can_tx_mode_t;
// Counter data as used by pyb.CAN.info() and machine.CAN.get_counters()
typedef struct {
unsigned tec;
unsigned rec;
unsigned tx_pending;
unsigned rx_fifo0_pending;
unsigned rx_fifo1_pending;
} can_counters_t;
#if defined(STM32H7)
#define CAN_TX_QUEUE_LEN 16
#else
// FDCAN STM32G4, bxCAN
#define CAN_TX_QUEUE_LEN 3
#endif
// RX FIFO numbering
//
// Note: For traditional CAN peripheral, the values of CAN_FIFO0 and CAN_FIFO1 are the same
// as this enum. FDCAN macros FDCAN_RX_FIFO0 and FDCAN_RX_FIFO1 are hardware offsets and not the same.
typedef enum {
CAN_RX_FIFO0,
CAN_RX_FIFO1,
} can_rx_fifo_t;
bool can_init(CAN_HandleTypeDef *can, int can_id, can_tx_mode_t tx_mode, uint32_t mode, uint32_t prescaler, uint32_t sjw, uint32_t bs1, uint32_t bs2, bool auto_restart);
void can_deinit(CAN_HandleTypeDef *can);
uint32_t can_get_source_freq(void);
int can_receive(CAN_HandleTypeDef *can, can_rx_fifo_t fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms);
// Transmit a CAN frame (callee to choose the transmit slot). Used by pyb.CAN only, does not enable TX interrupt
// On FDCAN this function invalidates the 'txmsg' structure if successful.
HAL_StatusTypeDef can_transmit(CAN_HandleTypeDef *hcan, CanTxMsgTypeDef *txmsg, uint8_t *data, uint32_t Timeout);
// Tell the controller to copy a CAN frame copied to 'index' and start transmitting
// On FDCAN this function invalidates the 'txmsg' structure if successful.
HAL_StatusTypeDef can_transmit_buf_index(CAN_HandleTypeDef *hcan, int index, CanTxMsgTypeDef *txmsg, const uint8_t *data);
// Cancel the pending transmission in the specified buffer index. Returns after buffer stops transmitting.
// Result is true if buffer was transmitting, false if not transmitting (or finished transmitting before cancellation)
bool can_cancel_transmit(CAN_HandleTypeDef *hcan, int index);
// Get the lowest index of a buffer in FAILED or SUCCEEDED state, or -1 if none exists
// Calling this function also re-enables the TX done IRQ for this peripheral
int can_get_transmit_finished(CAN_HandleTypeDef *hcan, bool *is_success);
// Disable all CAN receive interrupts for a FIFO
void can_disable_rx_interrupts(CAN_HandleTypeDef *can, can_rx_fifo_t fifo);
// Enable CAN receive interrupts for a FIFO.
//
// Interrupt for CAN_INT_MESSAGE_RECEIVED is only enabled if enable_msg_received is set.
void can_enable_rx_interrupts(CAN_HandleTypeDef *can, can_rx_fifo_t fifo, bool enable_msg_received);
// Disable all pending TX interrupts (ahead of restart or deinit). Will re-enable n next transmit
void can_disable_tx_interrupts(CAN_HandleTypeDef *can);
can_state_t can_get_state(CAN_HandleTypeDef *can);
void can_get_counters(CAN_HandleTypeDef *can, can_counters_t *counters);
// Restart controller (clears error states). Caller expected to check controller initialised already.
void can_restart(CAN_HandleTypeDef *can);
// Implemented in pyb_can.c, called from lower layer
extern void pyb_can_irq_handler(uint can_id, can_int_t interrupt, can_rx_fifo_t fifo);
// Implemented in machine_can.c, called from lower layer
extern void machine_can_irq_handler(uint can_id, can_int_t interrupt);
#if MICROPY_HW_ENABLE_FDCAN
static inline unsigned can_is_rx_pending(CAN_HandleTypeDef *can, can_rx_fifo_t fifo) {
return HAL_FDCAN_GetRxFifoFillLevel(can, fifo == CAN_RX_FIFO0 ? FDCAN_RX_FIFO0 : FDCAN_RX_FIFO1);
}
void can_clearfilter(CAN_HandleTypeDef *can, uint32_t filter_num, bool is_extid);
#else
static inline unsigned can_is_rx_pending(CAN_HandleTypeDef *can, can_rx_fifo_t fifo) {
return __HAL_CAN_MSG_PENDING(can, fifo == CAN_RX_FIFO0 ? CAN_FIFO0 : CAN_FIFO1);
}
void can_clearfilter(CAN_HandleTypeDef *can, uint32_t filter_num, uint8_t can2_start_bank);
#endif // MICROPY_HW_ENABLE_FDCAN
#endif // MICROPY_HW_ENABLE_CAN
#endif // MICROPY_INCLUDED_STM32_CAN_H