ENC28J60 is accessed via SPI1 (J16) or alternatively via SPI2 (J8/9) A bitbanging solution (for using alternative ports) will be provided later.
The chip has to be supplied with 3.3V!
MIOS32_ENC28J60_Init(0) has to be called only once to initialize the driver.
MIOS32_ENC28J60_CheckAvailable() should be called to connect with the device. If 0 is returned, it can be assumed that no ENC28J60 chip is connected. The function can be called periodically from a low priority task to retry a connection, resp. for an auto-detection during runtime
Most parts of the driver have been taken from ENC28J60.c file of the Microchip TCP/IP stack, and adapted to MIOS32 routines.
philetaylor (07 Jan 10): I have added mutex support. As many functions are not used externally they rely on the mutex being taked/given by the calling function. Please bear this in mind if calling functions directly. Only MIOS32_ENC28J60_Init(), MIOS32_ENC28J60_CheckAvailable() MIOS32_ENC28J60_PackageSend() and MIOS32_ENC28J60_PackageReceive() Will handle mutexes themselves all other functions will not.
#define BFC (0x5<<5) |
#define BFS (0x4<<5) |
#define CSN_0 { MIOS32_SPI_RC_PinSet(MIOS32_ENC28J60_SPI, MIOS32_ENC28J60_SPI_RC_PIN, 0); } |
#define CSN_1 { MIOS32_SPI_RC_PinSet(MIOS32_ENC28J60_SPI, MIOS32_ENC28J60_SPI_RC_PIN, 1); } |
#define MIOS32_ENC28J60_MUTEX_GIVE {} |
#define MIOS32_ENC28J60_MUTEX_TAKE {} |
#define RAMSIZE 0x2000 |
#define RBM ((0x1<<5) | 0x1A) |
#define RCR (0x0<<5) |
#define RXEND 0x0FFF |
#define RXSIZE (RXSTOP - RXSTART + 1) |
#define RXSTART 0x0000 |
#define RXSTOP ((TXSTART - 2) | 0x0001) |
#define SR ((0x7<<5) | 0x1F) |
#define TXEND 0x1fff |
#define TXSTART 0x1000 |
#define WBM ((0x3<<5) | 0x1A) |
#define WCR (0x2<<5) |
struct __attribute__ | ( | (packed) | ) | [read] |
Takes the high byte of a register address and changes the bank select bits in ETHCON1 to match.
[in] | reg | Register address with the high byte containing the two bank select bits. |
Sends the 8 bit BFC opcode/Address byte over the SPI and then sends the data in the next 8 SPI clocks
This routine is almost identical to the MIOS32_ENC28J60_WriteReg() and MIOS32_ENC28J60_BFSReg() functions. It is separate to maximize speed.
MIOS32_ENC28J60_BFCReg() must only be used on ETH registers.
[in] | address | 5 bit address of the register to modify. The top 3 bits must be 0 |
[in] | data | Byte to be used with the Bit Field Clear operation |
Sends the 8 bit BFS opcode/Address byte over the SPI and then sends the data in the next 8 SPI clocks
This routine is almost identical to the MIOS32_ENC28J60_WriteReg() and MIOS32_ENC28J60_BFCReg() functions. It is separate to maximize speed.
MIOS32_ENC28J60_BFSReg() must only be used on ETH registers.
[in] | address | 5 bit address of the register to modify. The top 3 bits must be 0 |
[in] | data | Byte to be used with the Bit Field Set operation |
Checks if the chip is still connected by reading the revision ID.
This takes ca. 2 uS
If the ID value is within the range of 0x01..0x1f, MIOS32_ENC28J60_PowerOn() will be called by this function to initialize the device completely.
Example for Connection/Disconnection detection:
// this function is called each second from a low-priority task // If multiple tasks are accessing the ENC28J60 chip, add a semaphore/mutex // to avoid IO access collisions with other tasks! u8 enc28j60_available; s32 ETHERNET_CheckENC28J60(void) { // check if ENC28J60 is connected u8 prev_enc28j60_available = enc28j60_available; enc28j60_available = MIOS32_ENC28J60_CheckAvailable(prev_enc28j60_available); if( enc28j60_available && !prev_enc28j60_available ) { // ENC28J60 has been connected // now it's possible to receive/send packages } else if( !enc28j60_available && prev_enc28j60_available ) { // ENC28J60 has been disconnected // here you can notify your application about this state } return 0; // no error }
[in] | was_available | should only be set if the ENC28J60 was previously available |
Initializes SPI pins and peripheral to access ENC28J60
[in] | mode | currently only mode 0 supported |
s32 MIOS32_ENC28J60_LinkAvailable | ( | void | ) |
Returns the PHSTAT1.LLSTAT bit (ethernet cable connected)
u8* MIOS32_ENC28J60_MAC_AddrGet | ( | void | ) |
Returns the current MAC address
Changes the MAC address.
Usually called by MIOS32_ENC28J60_PowerOn(), but could also be used during runtime.
The default MAC address is predefined by MIOS32_ENC28J60_MY_MAC_ADDR[123456] and can be overruled in mios32_config.h if desired.
[in] | new_mac_addr | an array with 6 bytes which define the MAC address. If all bytes are 0 (default), the serial number of STM32 will be taken instead, which should be unique in your private network. |
s32 MIOS32_ENC28J60_MACDiscardRx | ( | void | ) |
Marks the last received packet (obtained using MIOS32_ENC28J60_PackageReceive()) as being processed and frees the buffer memory associated with it
It is safe to call this function multiple times between MIOS32_ENC28J60_PackageReceive() calls. Extra packets won't be thrown away until MIOS32_ENC28J60_PackageReceive() makes it available.
s32 MIOS32_ENC28J60_MACGet | ( | void | ) |
Returns the byte pointed to by ERDPT and increments ERDPT so MIOS32_ENC28J60_MACGet() can be called again. The increment will follow the receive buffer wrapping boundary.
EWRPT is incremented after the read.
Burst reads several sequential bytes from the data buffer and places them into local memory. With SPI burst support, it performs much faster than multiple MIOS32_ENC28J60_MACGet() calls.
ERDPT is incremented after each byte, following the same rules as MIOS32_ENC28J60_MACGet()
[in] | buffer | target buffer |
[in] | len | number of bytes which should be read |
Outputs the Write Buffer Memory opcode/constant (8 bits) and data to write (8 bits) over the SPI.
EWRPT is incremented after the write.
[in] | value | Byte to write into the ENC28J60 buffer memory |
writes several sequential bytes to the ENC28J60 RAM. It performs faster than multiple MIOS32_ENC28J60_MACPut() calls.
EWRPT is incremented by len.
[in] | buffer | source buffer |
[in] | len | number of bytes which should be written |
Receives a package from ENC28J60 chip param[in] buffer Pointer to buffer which gets the playload param[in] buffer_size Max. number of bytes which can be received
Sends a package to the ENC28J60 chip param[in] buffer Pointer to buffer which contains the playload param[in] len number of bytes which should be sent param[in] buffer2 Pointer to optional second buffer which contains additional playload (can be NULL if no additional data) param[in] len2 number of bytes in second buffer (should be 0 if no additional data)
s32 MIOS32_ENC28J60_PowerOff | ( | void | ) |
s32 MIOS32_ENC28J60_PowerOn | ( | void | ) |
Connects to ENC28J60 chip
Sends the 8 bit RCR opcode/Address byte over the SPI and then retrives the register contents in the next 8 SPI clocks.
This routine cannot be used to access MAC/MII or PHY registers. Use MIOS32_ENC28J60_ReadMACReg() or MIOS32_ENC28J60_ReadPHYReg() for that purpose.
[in] | address | 5 bit address of the ETH control register to read from. |
Sends the 8 bit RCR opcode/Address byte as well as a dummy byte over the SPI and then retrives the register contents in the last 8 SPI clocks.
This routine cannot be used to access ETH or PHY registers. Use MIOS32_ENC28J60_ReadETHReg() or MIOS32_ENC28J60_ReadPHYReg() for that purpose.
[in] | address | 5 bit address of the MAC or MII register to read from. |
Performs an MII read operation. While in progress, it simply polls the MII BUSY bit wasting time (10.24us).
This routine cannot be used to access ETH or PHY registers. Use MIOS32_ENC28J60_ReadETHReg() or MIOS32_ENC28J60_ReadPHYReg() for that purpose.
[in] | reg | Address of the PHY register to read from. |
s32 MIOS32_ENC28J60_RevIDGet | ( | void | ) |
Returns ENC28J60 Revision ID
Value is only valid if MIOS32_ENC28J60_PowerOn() passed without errors.
s32 MIOS32_ENC28J60_SendSystemReset | ( | void | ) |
Sends the System Reset SPI command to the Ethernet controller. It resets all register contents (except for ECOCON) and returns the device to the power on default state.
Performs an MII write operation.
While in progress, it simply polls the MII BUSY bit wasting time.
Alters bank bits to point to Bank 3
[in] | reg | Address of the PHY register to write to. |
[in] | data | 16 bits of data to write to PHY register. |
Sends the 8 bit WCR opcode/Address byte over the SPI and then sends the data in the next 8 SPI clocks
This routine is almost identical to the MIOS32_ENC28J60_BFCReg() and MIOS32_ENC28J60_BFSReg() functions. It is separate to maximize speed.
Unlike the MIOS32_ENC28J60_ReadETHReg/MIOS32_ENC28J60_ReadMACReg functions, MIOS32_ENC28J60_WriteReg() can write to any ETH or MAC register. Writing to PHY registers must be accomplished with MIOS32_ENC28J60_WritePHYReg().
[in] | address | 5 bit address of the ETH, MAC, or MII register to modify. The top 3 bits must be 0 |
[in] | data | Byte to be written into register |