-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathenc28j60_eth_drv.h
346 lines (296 loc) · 9.56 KB
/
enc28j60_eth_drv.h
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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*
* Copyright (c) 2019 Tobias Jaster
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ENC28J60_ETH_DRV_H_
#define ENC28J60_ETH_DRV_H_
#include <stdint.h>
//#include "stdbool.h"
//#include "EMAC.h"
#include "mbed.h"
#include "rtos.h"
#include "rtos/Mutex.h"
#include "enc28j60.h"
#define ENC28J60_READWRITE
/**
* \brief Error code definitions
*
*/
typedef struct {
bool packet_handled = true;
uint16_t packet_state = 0;
uint32_t packet_pointer = 0;
uint32_t packet_data_pointer = 0;
uint16_t packet_len = 0;
uint32_t next_packet_pointer = RXSTART_INIT;
} enc28j60_rx_handle_t;
typedef struct {
bool packet_data_handled = true;
uint32_t packet_data_pointer = 0;
uint8_t packet_data_control = 0;
uint16_t packet_data_len = 0;
uint8_t packet_data_state[7] = {0};
bool next_fifo_filled = false;
uint32_t next_packet_data_pointer = TXSTART_INIT;
uint8_t next_packet_data_control = 0;
uint16_t next_packet_data_len = 0;
} enc28j60_tx_handle_t;
/**
* \brief Error code definitions
*
*/
typedef enum {
ENC28J60_ERROR_NONE = 0U, /*!< no error */
ENC28J60_ERROR_TIMEOUT = 1U, /*!< timeout */
ENC28J60_ERROR_BUSY = 2U, /*!< no error */
ENC28J60_ERROR_PARAM = 3U, /*!< invalid parameter */
ENC28J60_ERROR_INTERNAL = 4U, /*!< internal error */
ENC28J60_ERROR_WRONG_ID = 5U, /*!< internal error */
ENC28J60_ERROR_NOPACKET = 10U,
ENC28J60_ERROR_RECEIVE = 11U,
ENC28J60_ERROR_LASTPACKET = 12U,
ENC28J60_ERROR_POSITIONLENGTH = 13U, /*!< internal error */
ENC28J60_ERROR_SIZE = 20U, /*!< internal error */
ENC28J60_ERROR_FIFOFULL = 21U, /*!< internal error */
ENC28J60_ERROR_NEXTPACKET = 22U, /*!< internal error */
} enc28j60_error_t;
/**
* \brief Interrupt source definitions
*
*/
typedef enum {
ENC28J60_INTERRUPT_ENABLE = EIE_INTIE,
ENC28J60_INTERRUPT_RX_PENDING_ENABLE = EIE_PKTIE,
ENC28J60_INTERRUPT_DMA_ENABLE = EIE_DMAIE,
ENC28J60_INTERRUPT_LINK_STATE_ENABLE = EIE_LINKIE,
ENC28J60_INTERRUPT_TX_ENABLE = EIE_TXIE,
ENC28J60_INTERRUPT_TX_ERROR_ENABLE = EIE_TXERIE,
ENC28J60_INTERRUPT_RX_ERROR_ENABLE = EIE_RXERIE
}enc28j60_interrupt_source;
class ENC28J60_ETH_DRV {
public:
ENC28J60_ETH_DRV(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset);
ENC28J60_ETH_DRV(mbed::SPI *spi, PinName cs, PinName reset);
/**
* \brief Initializes ENC28J60 Ethernet controller to a known default state:
* - device ID is checked
* - global interrupt is enabled, but all irq sources are disabled
* - Establish link enabled
* - Rx enabled
* - Tx enabled
* Init should be called prior to any other process and
* it's the caller's responsibility to follow proper call order.
*
* \return error code /ref enc28j60_error_t
*/
enc28j60_error_t init(void);
/** This returns a unique 6-byte MAC address, based on the device UID
* This function overrides hal/common/mbed_interface.c function
* @param mac A 6-byte array to write the MAC address
*/
void mbed_mac_address(char *mac);
MBED_WEAK uint8_t mbed_otp_mac_address(char *mac);
void mbed_default_mac_address(char *mac);
/**
* \brief Read ENC28J60 ID.
*
* \return ID number
*/
uint32_t read_id(void);
/**
* \brief Initiates a hard reset.
*/
void hard_reset(bool state);
/**
* \brief Initiates a soft reset, returns failure or success.
*
* \return error code /ref enc28j60_error_t
*/
enc28j60_error_t soft_reset(void);
/**
* \brief Set maximum transition unit by Rx fifo size.
* Note: The MTU will be smaller by 512 bytes,
* because the status uses this fixed space.
*
* \param[in] val Size of the fifo in kbytes
*/
void set_rxfifo(uint32_t val);
/**
* \brief Initialise irqs by clearing and disabling all interrupt sources
* and enable interrupts. Since all interrupt sources are disabled,
* interrupt won't be triggered, until interrupt sources won't be
* enabled by \ref enc28j60_enable_interrupt
*/
void init_irqs(void);
/**
* \brief Check PHY ID registers.
*
* \param[in] dev Ethernet device structure \ref enc28j60_eth_dev_t
*/
enc28j60_error_t check_phy(void);
/**
* \brief Reset PHY
*
* \return error code /ref enc28j60_error_t
*/
enc28j60_error_t reset_phy(void);
/**
* \brief Enable transmission
*/
void enable_xmit(void);
/**
* \brief Disable transmission
*/
void disable_xmit(void);
/**
* \brief Enable receive
*/
void enable_mac_recv(void);
/**
* \brief Disable receive
*/
void disable_mac_recv(void);
/**
* \brief Enable the given interrupt source.
*
* \param[in] source Enum of the interrupt source.
*/
void enable_interrupt(enc28j60_interrupt_source source);
/**
* \brief Disable the given interrupt source.
*
* \param[in] source Enum of the interrupt source.
*/
void disable_interrupt(enc28j60_interrupt_source source);
/**
* \brief Disable all of the interrupt sources.
*/
void disable_all_interrupts(void);
/**
* \brief Clear the given interrupt source.
*
* \param[in] source Enum of the interrupt source.
*/
void clear_interrupt(enc28j60_interrupt_source source);
/**
* \brief Clear all of the interrupt sources.
*/
void clear_all_interrupts(void);
/**
* \brief Get the status of all interrupt sources.
*
* \return non-zero if the given interrupt source is triggered, zero otherwise
*/
uint8_t get_interrupts(void);
/**
* \brief Get the status of the given interrupt source.
*
* \param[in] source Enum of the interrupt source.
*
* \return non-zero if the given interrupt source is triggered, zero otherwise
*/
bool get_interrupt(enc28j60_interrupt_source source);
/**
* \brief Read MAC address from EEPROM.
*
* \param[in,out] mac array will include the read MAC address in
* 6 bytes hexadecimal format.
* It should be allocated by the caller to 6 bytes.
*
* \return error code /ref enc28j60_error_t
*/
enc28j60_error_t read_mac_address(char *mac);
/**
* \brief Write MAC address to EEPROM.
*
* \param[in,out] mac array will include the write MAC address in
* 6 bytes hexadecimal format.
* It should be allocated by the caller to 6 bytes.
*
* \return error code /ref enc28j60_error_t
*/
enc28j60_error_t write_mac_address(char *mac);
/**
* \brief Check device ID.
*
* \return error code /ref enc28j60_error_t
*/
bool check_id(void);
/**
* \brief Get the data size of the Rx buffer, aka Maximum Transition Unit
*
* \return Fifo data size in bytes
*/
uint32_t get_rx_data_fifo_size(void);
enc28j60_error_t tx_setWritePtr(uint16_t position, uint16_t offset);
uint32_t tx_get_fifo_data_used_space(void);
uint32_t tx_get_fifo_data_free_space(void);
enc28j60_error_t tx_send_next_packet(void);
enc28j60_error_t tx_write_data_fifo(uint8_t *data, uint16_t position, uint16_t size_bytes);
void tx_packetHandled(void);
/**
* \brief Get the used space of Rx fifo in bytes.
*
* \param[in] dev Ethernet device structure \ref enc28j60_eth_dev_t
*
* \return Data received and waiting for read in bytes
*/
uint32_t rx_get_fifo_data_used_space(void);
uint32_t rx_get_fifo_data_free_space(void);
/**
* \brief Get the size of next unread packet in Rx buffer, using the peak
* register, which is not destructive so can be read asynchronously.
* Warning: In case of heavy receiving load, it's possible this register
* is not perfectly in sync.
*
* \param[in] dev Ethernet device structure \ref enc28j60_eth_dev_t
*
* \return Size in bytes of the next packet can be read from Rx fifo, according
* to the peek register.
*/
enc28j60_error_t rx_setReadPtr(uint16_t position, uint16_t offset);//(uint16_t offset, uint16_t *len);
enc28j60_error_t rx_peek_next_packet(enc28j60_rx_handle_t *handle);
enc28j60_error_t rx_read_data_packet(uint8_t *data, uint16_t offset, uint16_t size_bytes);
void rx_packetHandled(void);
void rx_freeBuffer(void);
uint16_t rx_getReadPointer(void);
uint16_t rx_getWritePointer(void);
void readBuffer(uint16_t len, uint8_t* data);
void writeBuffer(uint16_t len, uint8_t* data);
uint8_t readReg(uint8_t address);
uint16_t readRegPair(uint8_t address);
void writeReg(uint8_t address, uint8_t data);
void writeRegPair(uint8_t address, uint16_t data);
enc28j60_error_t phyRead(uint8_t address, uint16_t *data);
enc28j60_error_t phyWrite(uint8_t address, uint16_t data);
bool linkStatus(void);
uint8_t readOp(uint8_t op, uint8_t address);
void writeOp(uint8_t op, uint8_t address, uint8_t data);
private:
void _setBank(uint8_t address);
void _read(uint8_t cmd, uint8_t *buf, uint16_t len, bool blocking);
void _write(uint8_t cmd, uint8_t *buf, uint8_t len, bool blocking);
#ifdef ENC28J60_READWRITE
void _readwrite(uint8_t cmd, uint8_t *readbuf, uint8_t *writebuf, uint8_t len, bool blocking);
#endif
mbed::SPI* _spi;
rtos::Mutex _SPIMutex;
DigitalOut _cs;
DigitalOut _reset;
bool _blocking;
uint8_t _bank;
enc28j60_rx_handle_t _rx_handle;
enc28j60_tx_handle_t _tx_handle;
};
#endif /* ENC28J60_ETH_DRV_H_ */