EMAC driver for the ENC28J60 Ethernet controller. This is a simplified fork of https://github.com/tobiasjaster/ENC28J60-EMAC-Driver published by Tobias Jaster.
Dependents: MQTT_Hello MQTT_HelloENC28J60
EMAC driver for the ENC28J60 Ethernet controller
This is a fork (the INT and RST pins are not used) of the ENC28J60-EMAC driver published by Tobias Jaster at
https://github.com/tobiasjaster/ENC28J60-EMAC-Driver
Usage:
- Connect the ENC28J60 module to the Mbed board as follows:
- Import (add) this ENC28J60-EMAC library to your program.
- Add a "mbed_app.json" file with the following content to the root directory of your program:
{ "target_overrides": { "*": { "platform.callback-nontrivial": true, "enc28j60-emac.mosi": "D11", "enc28j60-emac.miso": "D12", "enc28j60-emac.sck" : "D13", "enc28j60-emac.cs" : "D10" } } }
- Replace "D11", ..., "D10" with the actual pin names you selected on the Mbed board to be used for the SPI communication.
- To set the MAC address define an array with the desired address bytes and call the "set_hwaddr(mac)" function before calling the network interface "connect" function.
For example:
const uint8_t MAC[6] = { 0, 1, 2, 3, 4, 5 }; EthernetInterface net; int main() { net.get_emac().set_hwaddr(MAC); // set MAC address if (net.connect() != 0) { printf("Error: Unable to connect to the network.\n"); return -1; } ...
enc28j60_emac.h@1:bce04bfc41fe, 2021-03-27 (annotated)
- Committer:
- hudakz
- Date:
- Sat Mar 27 22:45:46 2021 +0000
- Revision:
- 1:bce04bfc41fe
- Parent:
- 0:b599e748252c
- Child:
- 2:19d290369c66
Mbed OS Ethernet MAC (EMAC) driver for the ENC28J60 Ethernet controller. This a simplified fork of https://github.com/tobiasjaster/ENC28J60-EMAC-Driver published by Tobias Jaster.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
hudakz | 0:b599e748252c | 1 | /* |
hudakz | 0:b599e748252c | 2 | * Copyright (c) 2019 Tobias Jaster |
hudakz | 0:b599e748252c | 3 | * |
hudakz | 0:b599e748252c | 4 | * Modified by Zoltan Hudak |
hudakz | 0:b599e748252c | 5 | * |
hudakz | 0:b599e748252c | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
hudakz | 0:b599e748252c | 7 | * you may not use this file except in compliance with the License. |
hudakz | 0:b599e748252c | 8 | * You may obtain a copy of the License at |
hudakz | 0:b599e748252c | 9 | * |
hudakz | 0:b599e748252c | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
hudakz | 0:b599e748252c | 11 | * |
hudakz | 0:b599e748252c | 12 | * Unless required by applicable law or agreed to in writing, software |
hudakz | 0:b599e748252c | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
hudakz | 0:b599e748252c | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
hudakz | 0:b599e748252c | 15 | * See the License for the specific language governing permissions and |
hudakz | 0:b599e748252c | 16 | * limitations under the License. |
hudakz | 0:b599e748252c | 17 | */ |
hudakz | 1:bce04bfc41fe | 18 | #ifndef ENC28J60_ETH_DRV_H_ |
hudakz | 1:bce04bfc41fe | 19 | #define ENC28J60_ETH_DRV_H_ |
hudakz | 0:b599e748252c | 20 | |
hudakz | 0:b599e748252c | 21 | #include "mbed.h" |
hudakz | 0:b599e748252c | 22 | #include "enc28j60_reg.h" |
hudakz | 0:b599e748252c | 23 | #include "enc28j60_emac_config.h" |
hudakz | 0:b599e748252c | 24 | |
hudakz | 1:bce04bfc41fe | 25 | #define ENC28J60_READWRITE 1 |
hudakz | 1:bce04bfc41fe | 26 | |
hudakz | 1:bce04bfc41fe | 27 | /** |
hudakz | 1:bce04bfc41fe | 28 | * \brief Error code definitions |
hudakz | 1:bce04bfc41fe | 29 | * |
hudakz | 1:bce04bfc41fe | 30 | */ |
hudakz | 1:bce04bfc41fe | 31 | typedef struct |
hudakz | 1:bce04bfc41fe | 32 | { |
hudakz | 1:bce04bfc41fe | 33 | uint8_t* buf; |
hudakz | 1:bce04bfc41fe | 34 | uint16_t len; |
hudakz | 1:bce04bfc41fe | 35 | } payload_t; |
hudakz | 1:bce04bfc41fe | 36 | |
hudakz | 1:bce04bfc41fe | 37 | typedef struct |
hudakz | 1:bce04bfc41fe | 38 | { |
hudakz | 1:bce04bfc41fe | 39 | uint32_t addr; |
hudakz | 1:bce04bfc41fe | 40 | payload_t payload; |
hudakz | 1:bce04bfc41fe | 41 | } packet_t; |
hudakz | 1:bce04bfc41fe | 42 | |
hudakz | 1:bce04bfc41fe | 43 | /** |
hudakz | 1:bce04bfc41fe | 44 | * \brief Error code definitions |
hudakz | 1:bce04bfc41fe | 45 | * |
hudakz | 1:bce04bfc41fe | 46 | */ |
hudakz | 1:bce04bfc41fe | 47 | typedef enum |
hudakz | 1:bce04bfc41fe | 48 | { |
hudakz | 1:bce04bfc41fe | 49 | ENC28J60_ERROR_OK = 0U, /*!< no error */ |
hudakz | 1:bce04bfc41fe | 50 | ENC28J60_ERROR_TIMEOUT = 1U, /*!< timeout */ |
hudakz | 1:bce04bfc41fe | 51 | ENC28J60_ERROR_BUSY = 2U, /*!< no error */ |
hudakz | 1:bce04bfc41fe | 52 | ENC28J60_ERROR_PARAM = 3U, /*!< invalid parameter */ |
hudakz | 1:bce04bfc41fe | 53 | ENC28J60_ERROR_INTERNAL = 4U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 54 | ENC28J60_ERROR_WRONG_ID = 5U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 55 | ENC28J60_ERROR_NOPACKET = 10U, |
hudakz | 1:bce04bfc41fe | 56 | ENC28J60_ERROR_RECEIVE = 11U, |
hudakz | 1:bce04bfc41fe | 57 | ENC28J60_ERROR_LASTPACKET = 12U, |
hudakz | 1:bce04bfc41fe | 58 | ENC28J60_ERROR_POSITIONLENGTH = 13U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 59 | ENC28J60_ERROR_SIZE = 20U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 60 | ENC28J60_ERROR_FIFOFULL = 21U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 61 | ENC28J60_ERROR_NEXTPACKET = 22U, /*!< internal error */ |
hudakz | 1:bce04bfc41fe | 62 | } enc28j60_error_t; |
hudakz | 1:bce04bfc41fe | 63 | |
hudakz | 1:bce04bfc41fe | 64 | /** |
hudakz | 1:bce04bfc41fe | 65 | * \brief Interrupt source definitions |
hudakz | 1:bce04bfc41fe | 66 | * |
hudakz | 1:bce04bfc41fe | 67 | */ |
hudakz | 1:bce04bfc41fe | 68 | typedef enum |
hudakz | 1:bce04bfc41fe | 69 | { |
hudakz | 1:bce04bfc41fe | 70 | ENC28J60_INTERRUPT_ENABLE = EIE_INTIE, |
hudakz | 1:bce04bfc41fe | 71 | ENC28J60_INTERRUPT_RX_PENDING_ENABLE= EIE_PKTIE, |
hudakz | 1:bce04bfc41fe | 72 | ENC28J60_INTERRUPT_DMA_ENABLE = EIE_DMAIE, |
hudakz | 1:bce04bfc41fe | 73 | ENC28J60_INTERRUPT_LINK_STATE_ENABLE= EIE_LINKIE, |
hudakz | 1:bce04bfc41fe | 74 | ENC28J60_INTERRUPT_TX_ENABLE = EIE_TXIE, |
hudakz | 1:bce04bfc41fe | 75 | ENC28J60_INTERRUPT_TX_ERROR_ENABLE = EIE_TXERIE, |
hudakz | 1:bce04bfc41fe | 76 | ENC28J60_INTERRUPT_RX_ERROR_ENABLE = EIE_RXERIE |
hudakz | 1:bce04bfc41fe | 77 | } enc28j60_interrupt_source; |
hudakz | 1:bce04bfc41fe | 78 | |
hudakz | 1:bce04bfc41fe | 79 | class ENC28J60 |
hudakz | 0:b599e748252c | 80 | { |
hudakz | 0:b599e748252c | 81 | public: |
hudakz | 1:bce04bfc41fe | 82 | ENC28J60(PinName mosi, PinName miso, PinName sclk, PinName cs); |
hudakz | 0:b599e748252c | 83 | |
hudakz | 1:bce04bfc41fe | 84 | ENC28J60(mbed::SPI * spi, PinName cs); |
hudakz | 0:b599e748252c | 85 | |
hudakz | 0:b599e748252c | 86 | /** |
hudakz | 1:bce04bfc41fe | 87 | * \brief Initializes ENC28J60 Ethernet controller to a known default state: |
hudakz | 1:bce04bfc41fe | 88 | * - device ID is checked |
hudakz | 1:bce04bfc41fe | 89 | * - global interrupt is enabled, but all irq sources are disabled |
hudakz | 1:bce04bfc41fe | 90 | * - Establish link enabled |
hudakz | 1:bce04bfc41fe | 91 | * - Rx enabled |
hudakz | 1:bce04bfc41fe | 92 | * - Tx enabled |
hudakz | 1:bce04bfc41fe | 93 | * Init should be called prior to any other process and |
hudakz | 1:bce04bfc41fe | 94 | * it's the caller's responsibility to follow proper call order. |
hudakz | 0:b599e748252c | 95 | * |
hudakz | 1:bce04bfc41fe | 96 | * \return error code /ref enc28j60_error_t |
hudakz | 0:b599e748252c | 97 | */ |
hudakz | 1:bce04bfc41fe | 98 | void init(void); |
hudakz | 0:b599e748252c | 99 | |
hudakz | 1:bce04bfc41fe | 100 | /** This returns a unique 6-byte MAC address, based on the device UID |
hudakz | 1:bce04bfc41fe | 101 | * This function overrides hal/common/mbed_interface.c function |
hudakz | 1:bce04bfc41fe | 102 | * @param mac A 6-byte array to write the MAC address |
hudakz | 1:bce04bfc41fe | 103 | */ |
hudakz | 1:bce04bfc41fe | 104 | void mbed_mac_address(char* mac); |
hudakz | 1:bce04bfc41fe | 105 | MBED_WEAK uint8_t mbed_otp_mac_address(char* mac); |
hudakz | 1:bce04bfc41fe | 106 | void mbed_default_mac_address(char* mac); |
hudakz | 0:b599e748252c | 107 | |
hudakz | 0:b599e748252c | 108 | /** |
hudakz | 1:bce04bfc41fe | 109 | * \brief Initiates a soft reset, returns failure or success. |
hudakz | 0:b599e748252c | 110 | * |
hudakz | 1:bce04bfc41fe | 111 | * \return error code /ref enc28j60_error_t |
hudakz | 0:b599e748252c | 112 | */ |
hudakz | 1:bce04bfc41fe | 113 | enc28j60_error_t softReset(void); |
hudakz | 0:b599e748252c | 114 | |
hudakz | 0:b599e748252c | 115 | /** |
hudakz | 1:bce04bfc41fe | 116 | * \brief Set maximum transition unit by Rx fifo size. |
hudakz | 1:bce04bfc41fe | 117 | * Note: The MTU will be smaller by 512 bytes, |
hudakz | 1:bce04bfc41fe | 118 | * because the status uses this fixed space. |
hudakz | 0:b599e748252c | 119 | * |
hudakz | 1:bce04bfc41fe | 120 | * \param[in] val Size of the fifo in kbytes |
hudakz | 0:b599e748252c | 121 | */ |
hudakz | 1:bce04bfc41fe | 122 | void setRxBufSize(uint32_t val); |
hudakz | 0:b599e748252c | 123 | |
hudakz | 0:b599e748252c | 124 | /** |
hudakz | 1:bce04bfc41fe | 125 | * \brief Reset PHY |
hudakz | 0:b599e748252c | 126 | * |
hudakz | 1:bce04bfc41fe | 127 | * \return error code /ref enc28j60_error_t |
hudakz | 1:bce04bfc41fe | 128 | */ |
hudakz | 1:bce04bfc41fe | 129 | enc28j60_error_t resetPhy(void); |
hudakz | 1:bce04bfc41fe | 130 | |
hudakz | 1:bce04bfc41fe | 131 | /** |
hudakz | 1:bce04bfc41fe | 132 | * \brief Enable receive |
hudakz | 0:b599e748252c | 133 | */ |
hudakz | 1:bce04bfc41fe | 134 | void enableMacRecv(void); |
hudakz | 1:bce04bfc41fe | 135 | |
hudakz | 1:bce04bfc41fe | 136 | /** |
hudakz | 1:bce04bfc41fe | 137 | * \brief Disable receive |
hudakz | 1:bce04bfc41fe | 138 | */ |
hudakz | 1:bce04bfc41fe | 139 | void disableMacRecv(void); |
hudakz | 0:b599e748252c | 140 | |
hudakz | 0:b599e748252c | 141 | /** |
hudakz | 1:bce04bfc41fe | 142 | * \brief Read MAC address from EEPROM. |
hudakz | 0:b599e748252c | 143 | * |
hudakz | 1:bce04bfc41fe | 144 | * \param[in,out] mac array will include the read MAC address in |
hudakz | 1:bce04bfc41fe | 145 | * 6 bytes hexadecimal format. |
hudakz | 1:bce04bfc41fe | 146 | * It should be allocated by the caller to 6 bytes. |
hudakz | 1:bce04bfc41fe | 147 | * |
hudakz | 1:bce04bfc41fe | 148 | * \return error code /ref enc28j60_error_t |
hudakz | 0:b599e748252c | 149 | */ |
hudakz | 1:bce04bfc41fe | 150 | enc28j60_error_t readMacAddr(char* mac); |
hudakz | 0:b599e748252c | 151 | |
hudakz | 0:b599e748252c | 152 | /** |
hudakz | 1:bce04bfc41fe | 153 | * \brief Write MAC address to EEPROM. |
hudakz | 0:b599e748252c | 154 | * |
hudakz | 1:bce04bfc41fe | 155 | * \param[in,out] mac array will include the write MAC address in |
hudakz | 1:bce04bfc41fe | 156 | * 6 bytes hexadecimal format. |
hudakz | 1:bce04bfc41fe | 157 | * It should be allocated by the caller to 6 bytes. |
hudakz | 1:bce04bfc41fe | 158 | * |
hudakz | 1:bce04bfc41fe | 159 | * \return error code /ref enc28j60_error_t |
hudakz | 0:b599e748252c | 160 | */ |
hudakz | 1:bce04bfc41fe | 161 | enc28j60_error_t writeMacAddr(char* mac); |
hudakz | 0:b599e748252c | 162 | |
hudakz | 0:b599e748252c | 163 | /** |
hudakz | 1:bce04bfc41fe | 164 | * \brief Check device ID. |
hudakz | 0:b599e748252c | 165 | * |
hudakz | 1:bce04bfc41fe | 166 | * \return error code /ref enc28j60_error_t |
hudakz | 0:b599e748252c | 167 | */ |
hudakz | 1:bce04bfc41fe | 168 | bool check_id(void); |
hudakz | 0:b599e748252c | 169 | |
hudakz | 0:b599e748252c | 170 | /** |
hudakz | 1:bce04bfc41fe | 171 | * \brief Get the data size of the Rx buffer, aka Maximum Transition Unit |
hudakz | 0:b599e748252c | 172 | * |
hudakz | 1:bce04bfc41fe | 173 | * \return Fifo data size in bytes |
hudakz | 0:b599e748252c | 174 | */ |
hudakz | 1:bce04bfc41fe | 175 | enc28j60_error_t setWritePrt(uint16_t position, uint16_t offset); |
hudakz | 1:bce04bfc41fe | 176 | enc28j60_error_t transmitPacket(packet_t* packet); |
hudakz | 1:bce04bfc41fe | 177 | enc28j60_error_t loadPacketInTxBuffer(packet_t* packet); |
hudakz | 0:b599e748252c | 178 | |
hudakz | 1:bce04bfc41fe | 179 | /** |
hudakz | 1:bce04bfc41fe | 180 | * \brief Get the free space of Rx fifo in bytes. |
hudakz | 0:b599e748252c | 181 | * |
hudakz | 1:bce04bfc41fe | 182 | * \param[in] dev Ethernet device structure \ref enc28j60_eth_dev_t |
hudakz | 1:bce04bfc41fe | 183 | * |
hudakz | 1:bce04bfc41fe | 184 | * \return Space available to store received data in bytes |
hudakz | 0:b599e748252c | 185 | */ |
hudakz | 1:bce04bfc41fe | 186 | uint32_t getRxBufFreeSpace(void); |
hudakz | 0:b599e748252c | 187 | |
hudakz | 1:bce04bfc41fe | 188 | /** |
hudakz | 1:bce04bfc41fe | 189 | * \brief Get the size of next unread packet in Rx buffer, using the peak |
hudakz | 1:bce04bfc41fe | 190 | * register, which is not destructive so can be read asynchronously. |
hudakz | 1:bce04bfc41fe | 191 | * Warning: In case of heavy receiving load, it's possible this register |
hudakz | 1:bce04bfc41fe | 192 | * is not perfectly in sync. |
hudakz | 0:b599e748252c | 193 | * |
hudakz | 1:bce04bfc41fe | 194 | * \param[in] dev Ethernet device structure \ref enc28j60_eth_dev_t |
hudakz | 1:bce04bfc41fe | 195 | * |
hudakz | 1:bce04bfc41fe | 196 | * \return Size in bytes of the next packet can be read from Rx fifo, according |
hudakz | 1:bce04bfc41fe | 197 | * to the peek register. |
hudakz | 0:b599e748252c | 198 | */ |
hudakz | 1:bce04bfc41fe | 199 | enc28j60_error_t setRxBufReadPtr(uint16_t position); |
hudakz | 1:bce04bfc41fe | 200 | enc28j60_error_t getPacketInfo(packet_t* packet); |
hudakz | 1:bce04bfc41fe | 201 | void readPacket(packet_t* packet); |
hudakz | 1:bce04bfc41fe | 202 | void freeRxBuffer(void); |
hudakz | 1:bce04bfc41fe | 203 | uint16_t getRecvPointer(void); |
hudakz | 1:bce04bfc41fe | 204 | uint16_t getWritePointer(void); |
hudakz | 1:bce04bfc41fe | 205 | void readBuf(uint8_t* data, uint16_t len); |
hudakz | 1:bce04bfc41fe | 206 | void writeBuf(uint8_t* data, uint16_t len); |
hudakz | 1:bce04bfc41fe | 207 | uint8_t readReg(uint8_t address); |
hudakz | 1:bce04bfc41fe | 208 | uint16_t readRegPair(uint8_t address); |
hudakz | 1:bce04bfc41fe | 209 | void writeReg(uint8_t address, uint8_t data); |
hudakz | 1:bce04bfc41fe | 210 | void writeRegPair(uint8_t address, uint16_t data); |
hudakz | 1:bce04bfc41fe | 211 | enc28j60_error_t phyRead(uint8_t address, uint16_t* data); |
hudakz | 1:bce04bfc41fe | 212 | enc28j60_error_t phyWrite(uint8_t address, uint16_t data); |
hudakz | 1:bce04bfc41fe | 213 | bool linkStatus(void); |
hudakz | 1:bce04bfc41fe | 214 | uint8_t readOp(uint8_t op, uint8_t address); |
hudakz | 1:bce04bfc41fe | 215 | void writeOp(uint8_t op, uint8_t address, uint8_t data); |
hudakz | 0:b599e748252c | 216 | private: |
hudakz | 1:bce04bfc41fe | 217 | void _setBank(uint8_t address); |
hudakz | 1:bce04bfc41fe | 218 | void _read(uint8_t cmd, uint8_t* buf, uint16_t len, bool blocking); |
hudakz | 1:bce04bfc41fe | 219 | void _write(uint8_t cmd, uint8_t* buf, uint16_t len, bool blocking); |
hudakz | 1:bce04bfc41fe | 220 | #ifdef ENC28J60_READWRITE |
hudakz | 1:bce04bfc41fe | 221 | void _readwrite(uint8_t cmd, uint8_t* readbuf, uint8_t* writebuf, uint16_t len, bool blocking); |
hudakz | 1:bce04bfc41fe | 222 | #endif |
hudakz | 1:bce04bfc41fe | 223 | SPI* _spi; |
hudakz | 1:bce04bfc41fe | 224 | Mutex _SPIMutex; |
hudakz | 1:bce04bfc41fe | 225 | DigitalOut _cs; |
hudakz | 1:bce04bfc41fe | 226 | uint8_t _bank; |
hudakz | 1:bce04bfc41fe | 227 | bool _ready; |
hudakz | 1:bce04bfc41fe | 228 | uint32_t _next; |
hudakz | 0:b599e748252c | 229 | }; |
hudakz | 1:bce04bfc41fe | 230 | #endif /* ENC28J60_ETH_DRV_H_ */ |