mirror of https://github.com/ARMmbed/mbed-os.git
add lan91c111 drivers for FVP MPS2 platfrom
parent
8a2044b5fc
commit
bbe3b131dc
|
@ -0,0 +1,368 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include "lan91c111.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static lan91_handle_t *lan91c111_handle;
|
||||
|
||||
void LAN91_init(void)
|
||||
{
|
||||
|
||||
uint32_t tcr, stat;
|
||||
|
||||
LAN91_ClearInterruptMasks();
|
||||
LAN91_Reset();
|
||||
|
||||
/* Clear control registers. */
|
||||
LAN91_SelectBank(0);
|
||||
LREG(uint16_t, B0_RCR) = 0;
|
||||
LREG(uint16_t, B0_TCR) = 0;
|
||||
|
||||
/* Write Configuration Registers */
|
||||
LAN91_SelectBank(1);
|
||||
LREG(uint16_t, B1_CR) = CR_EPH_POW_EN | CR_DEFAULT;
|
||||
|
||||
/* Reset the PHY*/
|
||||
write_PHY(0, 0x8000);
|
||||
|
||||
/* clear phy 18 status */
|
||||
read_PHY(18);
|
||||
|
||||
/* Use 100MBit link speed by default. */
|
||||
LAN91_SelectBank(0);
|
||||
LREG(uint16_t, B0_RPCR) = RPCR_SPEED | LEDA_10M_100M | LEDB_TX_RX;
|
||||
|
||||
/* Read Status Register */
|
||||
stat = read_PHY(18);
|
||||
|
||||
/* Set the Control Register */
|
||||
LAN91_SelectBank(1);
|
||||
LREG(uint16_t, B1_CTR) = CTR_LE_ENABLE | CTR_CR_ENABLE | CTR_TE_ENABLE | CTR_AUTO_REL | CTR_DEFAULT;
|
||||
|
||||
/* Setup Transmit Control Register. */
|
||||
tcr = TCR_TXENA | TCR_PAD_EN;
|
||||
if (stat & 0x0040) {
|
||||
tcr |= TCR_FDUPLX;
|
||||
}
|
||||
LREG(uint16_t, B0_TCR) = (uint16_t)tcr;
|
||||
|
||||
/* Reset MMU */
|
||||
LAN91_SelectBank(2);
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_RESET;
|
||||
while (LREG(uint16_t, B2_MMUCR) & MMUCR_BUSY);
|
||||
|
||||
/* Configure the Interrupts, allow RX_OVRN and RCV intr. */
|
||||
LAN91_SetInterruptMasks(MSK_RCV);
|
||||
|
||||
/* Set all buffers or data in handler for data transmit/receive process. */
|
||||
LAN91_SetHandler();
|
||||
}
|
||||
|
||||
void read_MACaddr(uint8_t *addr)
|
||||
{
|
||||
int i;
|
||||
|
||||
LAN91_SelectBank(1);
|
||||
|
||||
i = LREG(uint16_t, B1_IAR0);
|
||||
addr[0] = (uint8_t)i;
|
||||
addr[1] = (uint8_t)(i >> 8);
|
||||
|
||||
i = LREG(uint16_t, B1_IAR2);
|
||||
addr[2] = (uint8_t)i;
|
||||
addr[3] = (uint8_t)(i >> 8);
|
||||
|
||||
i = LREG(uint16_t, B1_IAR4);
|
||||
addr[4] = (uint8_t)i;
|
||||
addr[5] = (uint8_t)(i >> 8);
|
||||
}
|
||||
|
||||
void LAN91_SetCallback(lan91_callback_t callback, void *userData)
|
||||
{
|
||||
/* Set callback and userData. */
|
||||
lan91c111_handle->callback = callback;
|
||||
lan91c111_handle->userData = userData;
|
||||
}
|
||||
|
||||
|
||||
bool LAN91_send_frame(uint32_t *buff, uint32_t *size)
|
||||
{
|
||||
/* Send frame to Lan91C111 ethernet controller */
|
||||
uint16_t *dp;
|
||||
uint8_t packnr;
|
||||
int i;
|
||||
|
||||
LAN91_SelectBank(2);
|
||||
|
||||
/* MMU allocate memory for transmitting*/
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_ALLOC_TX;
|
||||
|
||||
/* Check if Interrupt Status Register been set for MMU Allocate Ready */
|
||||
if (!(LREG(uint16_t, B2_IST) & IST_ALLOC_INT))
|
||||
{
|
||||
/* Failed, Reset MMU */
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_RESET;
|
||||
while (LREG(uint16_t, B2_MMUCR) & MMUCR_BUSY);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set TX package number from allocated package number
|
||||
and also set pointer register as Auto Increase, write and transmit set */
|
||||
packnr = LREG(uint8_t, B2_ARR);
|
||||
LREG(uint8_t, B2_PNR) = packnr;
|
||||
LREG(uint16_t, B2_PTR) = PTR_AUTO_INCR;
|
||||
|
||||
/* Reserve space for Status Word */
|
||||
LREG(uint16_t, B2_DATA0) = 0x0000;
|
||||
/* Total = Raw Data Size + STATUS WORD + BYTE COUNT + CONTROL BYTE + LAST BYTE */
|
||||
LREG(uint16_t, B2_DATA0) = (uint16_t) * size + 6;
|
||||
|
||||
/* Copy frame data to Ethernet controller */
|
||||
dp = (uint16_t *)buff;
|
||||
for (i = *size; i > 1; i -= 2) {
|
||||
LREG(uint16_t, B2_DATA0) = *dp++;
|
||||
}
|
||||
|
||||
/* If data is odd , Add a control word and odd byte. */
|
||||
if (i) {
|
||||
LREG(uint16_t, B2_DATA0) = (RFC_CRC | RFC_ODD) | (*dp & 0xFF);
|
||||
} else {
|
||||
/* Add control word. */
|
||||
LREG(uint16_t, B2_DATA0) = RFC_CRC;
|
||||
}
|
||||
|
||||
LAN91_SelectBank(0);
|
||||
/* Enable transmitter. */
|
||||
LREG(uint16_t, B0_TCR) = TCR_TXENA | TCR_PAD_EN;
|
||||
|
||||
/* Enqueue the packet. */
|
||||
LAN91_SelectBank(2);
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_ENQ_TX;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool LAN91_receive_frame(uint32_t *buff, uint32_t *size)
|
||||
{
|
||||
uint32_t State, RxLen;
|
||||
uint32_t val, *dp;
|
||||
|
||||
/* No receive packets queued in Rx FIFO queue */
|
||||
LAN91_SelectBank(2);
|
||||
State = LREG(uint16_t, B2_FIFO);
|
||||
if (State & FIFO_REMPTY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Pointer Register set to RCV + Auto Increase + Read access
|
||||
So that Data Register is use RX FIFO*/
|
||||
LREG(uint16_t, B2_PTR) = PTR_RCV | PTR_AUTO_INCR | PTR_READ;
|
||||
|
||||
/* Read status word and packet length */
|
||||
val = LREG(uint32_t, B2_DATA);
|
||||
State = val & 0xFFFF;
|
||||
/* Raw Data Size = Total - STATUS WORD - BYTE COUNT - CONTROL BYTE - LAST BYTE */
|
||||
RxLen = (val >> 16) - 6;
|
||||
|
||||
/* Check State word if Odd number of bytes in a frame. */
|
||||
if (State & RFS_ODDFRM) {
|
||||
RxLen++;
|
||||
}
|
||||
|
||||
/* Packet too big, ignore it and free MMU and continue */
|
||||
if (RxLen > LAN91_ETH_MTU_SIZE) {
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_REMV_REL_RX;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buff != NULL) {
|
||||
/* Make sure that block is dword aligned */
|
||||
RxLen = (RxLen + 3) >> 2;
|
||||
*size = RxLen << 2;
|
||||
dp = buff;
|
||||
for (; RxLen; RxLen--) {
|
||||
*dp++ = LREG(uint32_t, B2_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
/* MMU free packet. Remove and Relase from TOP of RX */
|
||||
LREG(uint16_t, B2_MMUCR) = MMU_REMV_REL_RX;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ETHERNET_Handler(void)
|
||||
{
|
||||
LAN91_SelectBank(2);
|
||||
if((LREG(uint8_t, B2_IST) & IST_RCV) !=0)
|
||||
{
|
||||
LREG(uint8_t, B2_MSK) = 0;
|
||||
/* Callback function. */
|
||||
if (lan91c111_handle->callback) {
|
||||
lan91c111_handle->callback(LAN91_RxEvent, lan91c111_handle->userData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lan91_phy_status_t LAN91_GetLinkStatus(void)
|
||||
{
|
||||
if (read_PHY(0x2u) & 0x4u)
|
||||
{
|
||||
return STATE_LINK_UP;
|
||||
}
|
||||
else
|
||||
{
|
||||
return STATE_LINK_DOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void output_MDO(int bit_value)
|
||||
{
|
||||
uint32_t val = MGMT_MDOE;
|
||||
|
||||
if (bit_value) {
|
||||
val |= MGMT_MDO;
|
||||
}
|
||||
LREG(uint16_t, B3_MGMT) = (uint16_t)val;
|
||||
LREG(uint16_t, B3_MGMT) = (uint16_t)(val | MGMT_MCLK);
|
||||
LREG(uint16_t, B3_MGMT) = (uint16_t)val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int input_MDI(void)
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MCLK;
|
||||
if (LREG(uint16_t, B3_MGMT) & MGMT_MDI) {
|
||||
val = 1;
|
||||
}
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
return (val);
|
||||
}
|
||||
|
||||
static void write_PHY(uint32_t PhyReg, int Value)
|
||||
{
|
||||
int i;
|
||||
|
||||
LAN91_SelectBank(3);
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO;
|
||||
|
||||
/* 32 consecutive ones on MDO to establish sync */
|
||||
for (i = 0; i < 32; i++) {
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO | MGMT_MCLK;
|
||||
}
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE;
|
||||
|
||||
/* start code (01) */
|
||||
output_MDO(0);
|
||||
output_MDO(1);
|
||||
|
||||
/* write command (01) */
|
||||
output_MDO(0);
|
||||
output_MDO(1);
|
||||
|
||||
/* write PHY address - which is five 0s for 91C111 */
|
||||
for (i = 0; i < 5; i++) {
|
||||
output_MDO(0);
|
||||
}
|
||||
|
||||
/* write the PHY register to write (highest bit first) */
|
||||
for (i = 0; i < 5; i++) {
|
||||
output_MDO((PhyReg >> 4) & 0x01);
|
||||
PhyReg <<= 1;
|
||||
}
|
||||
|
||||
/* turnaround MDO */
|
||||
output_MDO(1);
|
||||
output_MDO(0);
|
||||
|
||||
/* write the data value (highest bit first) */
|
||||
for (i = 0; i < 16; i++) {
|
||||
output_MDO((Value >> 15) & 0x01);
|
||||
Value <<= 1;
|
||||
}
|
||||
|
||||
/* turnaround MDO is tristated */
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MCLK;
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
}
|
||||
|
||||
|
||||
static uint16_t read_PHY(uint32_t PhyReg)
|
||||
{
|
||||
int i, val;
|
||||
|
||||
LAN91_SelectBank(3);
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO;
|
||||
|
||||
/* 32 consecutive ones on MDO to establish sync */
|
||||
for (i = 0; i < 32; i++) {
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE | MGMT_MDO | MGMT_MCLK;
|
||||
}
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MDOE;
|
||||
|
||||
/* start code (01) */
|
||||
output_MDO(0);
|
||||
output_MDO(1);
|
||||
|
||||
/* read command (10) */
|
||||
output_MDO(1);
|
||||
output_MDO(0);
|
||||
|
||||
/* write PHY address - which is five 0s for 91C111 */
|
||||
for (i = 0; i < 5; i++) {
|
||||
output_MDO(0);
|
||||
}
|
||||
|
||||
/* write the PHY register to read (highest bit first) */
|
||||
for (i = 0; i < 5; i++) {
|
||||
output_MDO((PhyReg >> 4) & 0x01);
|
||||
PhyReg <<= 1;
|
||||
}
|
||||
|
||||
/* turnaround MDO is tristated */
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MCLK;
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
|
||||
/* read the data value */
|
||||
val = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
val <<= 1;
|
||||
val |= input_MDI();
|
||||
}
|
||||
|
||||
/* turnaround MDO is tristated */
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
LREG(uint16_t, B3_MGMT) = MGMT_MCLK;
|
||||
LREG(uint16_t, B3_MGMT) = 0;
|
||||
|
||||
return (val);
|
||||
}
|
|
@ -0,0 +1,413 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2018 ARM Limited
|
||||
*
|
||||
* 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 __LAN91C111_H
|
||||
#define __LAN91C111_H
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "PeripheralNames.h"
|
||||
|
||||
/* LAN91C111 base address used IO mode. */
|
||||
#define ADROFS 0x40200000
|
||||
|
||||
/* LAN91C111 Ethernet buffer alignment. */
|
||||
#define LAN91_BUFF_ALIGNMENT 16U
|
||||
|
||||
#define LAN91_ETH_MTU_SIZE 1500
|
||||
|
||||
/* Absolute access to LAN91C111 registers macro */
|
||||
#define LREG(object, reg) (*((object volatile *) (ADROFS+reg)))
|
||||
|
||||
/*******************************************************************************
|
||||
* Register Definations
|
||||
******************************************************************************/
|
||||
|
||||
/* Bank Select defines */
|
||||
#define BSR 0x0E /* Bank Select register common to all banks */
|
||||
#define BSR_MASK 0x03 /* Mask constant part of bank register */
|
||||
#define BSR_UPPER 0x3300 /* Constant value for upper byte of BSR */
|
||||
|
||||
/* Bank 0 Registers */
|
||||
#define B0_TCR 0x00 /* Transmit Control Register rd/wr */
|
||||
#define B0_EPHSR 0x02 /* EPH Status Register rd */
|
||||
#define B0_RCR 0x04 /* Receive Control Register rd/wr */
|
||||
#define B0_ECR 0x06 /* Counter Register rd */
|
||||
#define B0_MIR 0x08 /* Memory Information Register rd */
|
||||
#define B0_RPCR 0x0A /* Receive/Phy Control Register rd/wr */
|
||||
#define B0_RES 0x0C /* Reserved */
|
||||
|
||||
/* Bank 1 Registers */
|
||||
#define B1_CR 0x00 /* Configuration Register rd/wr */
|
||||
#define B1_BAR 0x02 /* Base Address Register rd/wr */
|
||||
#define B1_IAR 0x04 /* Individual Address Registers rd/wr */
|
||||
#define B1_IAR0 0x04 /* Individual Address Bytes 0-1 rd/wr */
|
||||
#define B1_IAR2 0x06 /* Individual Address Bytes 2-3 rd/wr */
|
||||
#define B1_IAR4 0x08 /* Individual Address Bytes 4-5 rd/wr */
|
||||
#define B1_GPR 0x0A /* General Purpose Register rd/wr */
|
||||
#define B1_CTR 0x0C /* Control Register rd/wr */
|
||||
|
||||
/* Bank 2 Registers */
|
||||
#define B2_MMUCR 0x00 /* MMU Command Register rd/wr */
|
||||
#define B2_PNR 0x02 /* Packet Number Register (8 bit) rd/wr */
|
||||
#define B2_ARR 0x03 /* Allocation Result Register (8 bit) rd */
|
||||
#define B2_FIFO 0x04 /* FIFO Ports Register rd */
|
||||
#define B2_TX_FIFO 0x04 /* Tx FIFO Packet Number (8 bit) rd */
|
||||
#define B2_RX_FIFO 0x05 /* Rx FIFO Packet Number (8 bit) rd */
|
||||
#define B2_PTR 0x06 /* Pointer Register rd/wr */
|
||||
#define B2_DATA 0x08 /* Data Register (8/16/32 bit) rd/wr */
|
||||
#define B2_DATA0 0x08 /* Data Register Word 0 rd/wr */
|
||||
#define B2_DATA1 0x0A /* Data Register Word 1 rd/wr */
|
||||
#define B2_IST 0x0C /* Interrupt Status Register (8 bit) rd */
|
||||
#define B2_ACK 0x0C /* Interrupt Ack Register (8 bit) wr */
|
||||
#define B2_MSK 0x0D /* Interrupt Mask Register (8 bit) rd/wr */
|
||||
|
||||
/* Bank 3 Registers */
|
||||
#define B3_MT 0x00 /* Multicast Hash Table rd/wr */
|
||||
#define B3_MT0 0x00 /* Multicast Hash Table 0-1 rd/wr */
|
||||
#define B3_MT2 0x02 /* Multicast Hash Table 2-3 rd/wr */
|
||||
#define B3_MT4 0x04 /* Multicast Hash Table 4-5 rd/wr */
|
||||
#define B3_MT6 0x06 /* Multicast Hash Table 6-7 rd/wr */
|
||||
#define B3_MGMT 0x08 /* Management Interface PHY rd/wr */
|
||||
#define B3_REV 0x0A /* Revision Register (Chip Id/Revision)rd/wr */
|
||||
#define B3_ERCV 0x0C /* Early Receive Register rd/wr */
|
||||
|
||||
|
||||
/*-----TCR control bits-----*/
|
||||
#define TCR_SWFDUP 0x8000 /* Switched Full Duplex Mode */
|
||||
#define TCR_EPH_LOOP 0x2000 /* Internal Loopback at the EPH block */
|
||||
#define TCR_STP_SQET 0x1000 /* Stop transmit on SQET error */
|
||||
#define TCR_FDUPLX 0x0800 /* Full duplex mode (receive own frames) */
|
||||
#define TCR_MON_CSN 0x0400 /* Monitor carrier while transmitting */
|
||||
#define TCR_NOCRC 0x0100 /* Don't append CRC to tx frames */
|
||||
#define TCR_PAD_EN 0x0080 /* Pad short frames with 0 if len < 64 bytes */
|
||||
#define TCR_FORCOL 0x0004 /* Force collision */
|
||||
#define TCR_LOOP 0x0002 /* PHY Local loopback */
|
||||
#define TCR_TXENA 0x0001 /* Enable transmitter */
|
||||
|
||||
/*-----EPHSR status bits-----*/
|
||||
#define EPHSR_TXUNRN 0x8000 /* Transmit Under Run */
|
||||
#define EPHSR_LINK_OK 0x4000 /* General purpose input driven by nLNK pin */
|
||||
#define EPHSR_CTR_ROL 0x1000 /* Counter Roll Over */
|
||||
#define EPHSR_EXC_DEF 0x0800 /* Excessive Deferral */
|
||||
#define EPHSR_LOST_CARR 0x0400 /* Lost Carrier Sense */
|
||||
#define EPHSR_LATCOL 0x0200 /* Late Collision Detected */
|
||||
#define EPHSR_TX_DEFR 0x0080 /* Transmit Deferred */
|
||||
#define EPHSR_LTX_BRD 0x0040 /* Last Tx Frame was a broadcast */
|
||||
#define EPHSR_SQET 0x0020 /* Signal Quality Error Test */
|
||||
#define EPHSR_16COL 0x0010 /* 16 collisions reached */
|
||||
#define EPHSR_LTX_MULT 0x0008 /* Last transmit frame was a multicast */
|
||||
#define EPHSR_MULCOL 0x0004 /* Multiple collision detected for last tx */
|
||||
#define EPHSR_SNGLCOL 0x0002 /* Single collision detected for last tx */
|
||||
#define EPHSR_TX_SUC 0x0001 /* Last transmit was successful */
|
||||
|
||||
/*-----RCR control bits-----*/
|
||||
#define RCR_SOFT_RST 0x8000 /* Software-Activated Reset */
|
||||
#define RCR_FILT_CAR 0x4000 /* Filter Carrier */
|
||||
#define RCR_ABORT_ENB 0x2000 /* Enable Abort of Rx when collision */
|
||||
#define RCR_STRIP_CRC 0x0200 /* Strip CRC of received frames */
|
||||
#define RCR_RXEN 0x0100 /* Enable Receiver */
|
||||
#define RCR_ALMUL 0x0004 /* Accept all multicast (no filtering) */
|
||||
#define RCR_PRMS 0x0002 /* Promiscuous mode */
|
||||
#define RCR_RX_ABORT 0x0001 /* Receive frame aborted (too long) */
|
||||
|
||||
/*-----RPCR control bits-----*/
|
||||
#define RPCR_SPEED 0x2000 /* Speed select input (10/100 MBps) */
|
||||
#define RPCR_DPLX 0x1000 /* Duplex Select (Full/Half Duplex) */
|
||||
#define RPCR_ANEG 0x0800 /* Auto-Negotiation mode select */
|
||||
#define RPCR_LEDA_MASK 0x00E0 /* LEDA signal mode select */
|
||||
#define RPCR_LEDB_MASK 0x001C /* LEDB signal mode select */
|
||||
|
||||
/*-----LEDA ON modes-----*/
|
||||
#define LEDA_10M_100M 0x0000 /* 10 MB or 100 MB link detected */
|
||||
#define LEDA_10M 0x0040 /* 10 MB link detected */
|
||||
#define LEDA_FDUPLX 0x0060 /* Full Duplex Mode enabled */
|
||||
#define LEDA_TX_RX 0x0080 /* Transmit or Receive packet occurred */
|
||||
#define LEDA_100M 0x00A0 /* 100 MB link detected */
|
||||
#define LEDA_RX 0x00C0 /* Receive packet occurred */
|
||||
#define LEDA_TX 0x00E0 /* Transmit packet occurred */
|
||||
|
||||
/*-----LEDA ON modes-----*/
|
||||
#define LEDB_10M_100M 0x0000 /* 10 MB or 100 MB link detected */
|
||||
#define LEDB_10M 0x0008 /* 10 MB link detected */
|
||||
#define LEDB_FDUPLX 0x000C /* Full Duplex Mode enabled */
|
||||
#define LEDB_TX_RX 0x0010 /* Transmit or Receive packet occurred */
|
||||
#define LEDB_100M 0x0014 /* 100 MB link detected */
|
||||
#define LEDB_RX 0x0018 /* Receive packet occurred */
|
||||
#define LEDB_TX 0x001C /* Transmit packet occurred */
|
||||
|
||||
/*-----CR control bits-----*/
|
||||
#define CR_EPH_POW_EN 0x8000 /* EPH Power Enable (0= power down PHY) */
|
||||
#define CR_NO_WAIT 0x1000 /* No wait states */
|
||||
#define CR_GPCNTRL 0x0400 /* General purpose Output drives nCNTRL pin */
|
||||
#define CR_EXT_PHY 0x0200 /* External PHY enabled (0= internal PHY) */
|
||||
#define CR_DEFAULT 0x20B1 /* Default bits set to 1 for write */
|
||||
|
||||
/*-----CTR control bits-----*/
|
||||
#define CTR_RCV_BAD 0x4000 /* Bad CRC packet received */
|
||||
#define CTR_AUTO_REL 0x0800 /* Auto-release Tx memory */
|
||||
#define CTR_LE_ENABLE 0x0080 /* Link error enable (mux into EPH int) */
|
||||
#define CTR_CR_ENABLE 0x0040 /* Counter rollover enable (mux into EPH int)*/
|
||||
#define CTR_TE_ENABLE 0x0020 /* Transmit error enable (mux into EPH int) */
|
||||
#define CTR_EEPROM_SEL 0x0004 /* EEPROM select */
|
||||
#define CTR_RELOAD 0x0002 /* Reload from EEPROM */
|
||||
#define CTR_STORE 0x0001 /* Store to EEPROM */
|
||||
#define CTR_DEFAULT 0x1210 /* Default bits set to 1 for write */
|
||||
|
||||
/*-----MMUCR control bits-----*/
|
||||
#define MMUCR_CMD_MASK 0x00E0 /* MMU Command mask */
|
||||
#define MMUCR_BUSY 0x0001 /* MMU processing a release command */
|
||||
|
||||
/*-----MMUCR Commands------*/
|
||||
#define MMU_NOOP 0x0000 /* No operation */
|
||||
#define MMU_ALLOC_TX 0x0020 /* Allocate memory for Tx */
|
||||
#define MMU_RESET 0x0040 /* Reset MMU to initial state */
|
||||
#define MMU_REMV_RX 0x0060 /* Remove frame from top of Rx FIFO */
|
||||
#define MMU_REMV_REL_RX 0x0080 /* Remove and Release top of Rx FIFO */
|
||||
#define MMU_REL_PKT 0x00A0 /* Release specific packet */
|
||||
#define MMU_ENQ_TX 0x00C0 /* Enqueue packet number into Tx FIFO */
|
||||
#define MMU_RESET_TX 0x00E0 /* Reset Tx FIFO */
|
||||
|
||||
/*-----FIFO status bits-----*/
|
||||
#define FIFO_REMPTY 0x8000 /* No receive packets queued in Rx FIFO */
|
||||
#define FIFO_TEMPTY 0x0080 /* No transmit packets in completion queue */
|
||||
|
||||
/*-----PTR control bits-----*/
|
||||
#define PTR_RCV 0x8000 /* Address refers to Rx area (0= Tx area) */
|
||||
#define PTR_AUTO_INCR 0x4000 /* Auto increment on access */
|
||||
#define PTR_READ 0x2000 /* Read access (0= write access) */
|
||||
#define PTR_ETEN 0x1000 /* Enable early transmit underrun detection */
|
||||
#define PTR_NOT_EMPTY 0x0800 /* Data FIFO not empty yet (read only bit) */
|
||||
#define PTR_MASK 0x03FF /* Mask pointer value */
|
||||
|
||||
/*-----IST status bits-----*/
|
||||
#define IST_MDINT 0x80 /* PHY MI Register 18 change status interrupt*/
|
||||
#define IST_ERCV_INT 0x40 /* Early Receive interrupt */
|
||||
#define IST_EPH_INT 0x20 /* EPH Type interrupt */
|
||||
#define IST_RX_OVRN 0x10 /* Receive Overrun interrupt */
|
||||
#define IST_ALLOC_INT 0x08 /* Tx ram Allocation interrupt */
|
||||
#define IST_TX_EMPTY 0x04 /* Tx FIFO empty interrupt */
|
||||
#define IST_TX_INT 0x02 /* Tx Complete interrupt */
|
||||
#define IST_RCV 0x01 /* Rx Complete intererupt */
|
||||
|
||||
/*-----ACK control bits-----*/
|
||||
#define ACK_MDINT 0x80 /* PHY MI Register 18 change int. ack */
|
||||
#define ACK_ERCV_INT 0x40 /* Early Receive int. ack */
|
||||
#define ACK_RX_OVRN 0x10 /* Receive Overrun int. ack */
|
||||
#define ACK_TX_EMPTY 0x04 /* Tx FIFO empty int. ack */
|
||||
#define ACK_TX_INT 0x02 /* Tx Complete int. ack */
|
||||
|
||||
/*-----MSK control bits-----*/
|
||||
#define MSK_MDINT 0x80 /* PHY MI Register 18 change int. mask */
|
||||
#define MSK_ERCV_INT 0x40 /* Early Receive int. mask */
|
||||
#define MSK_EPH_INT 0x20 /* EPH Type int. mask */
|
||||
#define MSK_RX_OVRN 0x10 /* Receive Overrun int. mask */
|
||||
#define MSK_ALLOC_INT 0x08 /* Tx ram Allocation int. mask */
|
||||
#define MSK_TX_EMPTY 0x04 /* Tx FIFO empty int. mask */
|
||||
#define MSK_TX_INT 0x02 /* Tx Complete int. mask */
|
||||
#define MSK_RCV 0x01 /* Rx Complete int. mask */
|
||||
|
||||
/*-----MGMT control bits-----*/
|
||||
#define MGMT_MSK_CRS100 0x0040 /* Disables CRS100 detection in Tx Half Dupl.*/
|
||||
#define MGMT_MDOE 0x0008 /* MII - 1= MDO pin output, 0= MDO tristated */
|
||||
#define MGMT_MCLK 0x0004 /* MII - Value drives MDCLK pin */
|
||||
#define MGMT_MDI 0x0002 /* MII - Value of MDI pin when read */
|
||||
#define MGMT_MDO 0x0001 /* MII - Value drives MDO pin */
|
||||
#define MGMT_DEFAULT 0x3330 /* Default bits set to 1 for write */
|
||||
|
||||
/*----- Receive Frame Status -----*/
|
||||
#define RFS_ALGNERR 0x8000 /* Frame alignment error */
|
||||
#define RFS_BROADCAST 0x4000 /* Received broadcast frame */
|
||||
#define RFS_BADCRC 0x2000 /* Bad CRC error */
|
||||
#define RFS_ODDFRM 0x1000 /* Frame with Odd number of bytes received */
|
||||
#define RFS_TOOLNG 0x0800 /* Too long frame received (max. 1518 bytes) */
|
||||
#define RFS_TOOSHORT 0x0400 /* Too short frame received (min. 64 bytes) */
|
||||
#define RFS_MULTCAST 0x0001 /* Multicast frame received */
|
||||
#define RFS_HASH_MASK 0x007E /* Hash value index for multicast registers */
|
||||
|
||||
/*----- Receive Frame Control -----*/
|
||||
#define RFC_ODD 0x2000 /* Odd number of bytes in frame */
|
||||
#define RFC_CRC 0x1000 /* Append CRC (valid when TCR_NOCRC = 1) */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Data Stractures
|
||||
******************************************************************************/
|
||||
|
||||
/*! @brief List of interrupts supported by the peripheral. This
|
||||
* enumeration uses one-bot encoding to allow a logical OR of multiple
|
||||
* members. Members usually map to interrupt enable bits in one or more
|
||||
* peripheral registers.
|
||||
*/
|
||||
typedef enum _lan91_phy_status
|
||||
{
|
||||
STATE_UNKNOWN = (-1), /* PHY MI Register 18 change status interrupt*/
|
||||
STATE_LINK_DOWN = (0), /* EPH Type interrupt */
|
||||
STATE_LINK_UP = (1) /* Receive Overrun interrupt */
|
||||
} lan91_phy_status_t;
|
||||
|
||||
/*! @brief Defines the common interrupt event for callback use. */
|
||||
typedef enum _lan91_event
|
||||
{
|
||||
LAN91_RxEvent, /*!< Receive event. */
|
||||
LAN91_TxEvent, /*!< Transmit event. */
|
||||
LAN91_ErrEvent /*!< Error event: BABR/BABT/EBERR/LC/RL/UN/PLR . */
|
||||
} lan91_event_t;
|
||||
|
||||
|
||||
/* ------------------------------- Call back ---------------------------------*/
|
||||
/* Forward declaration of the handle typedef. */
|
||||
typedef struct _lan91_handle lan91_handle_t;
|
||||
|
||||
|
||||
/*! @brief ENET callback function. */
|
||||
typedef void (*lan91_callback_t)( lan91_event_t event, void *userData);
|
||||
|
||||
|
||||
/*! @brief Defines the ENET handler structure. */
|
||||
struct _lan91_handle
|
||||
{
|
||||
lan91_callback_t callback; /*!< Callback function. */
|
||||
void *userData; /*!< Callback function parameter.*/
|
||||
};
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* functions
|
||||
******************************************************************************/
|
||||
|
||||
/** @brief Initialize the Lan91C111 ethernet controller. */
|
||||
void LAN91_init (void);
|
||||
|
||||
/** @brief Read MAC address stored to external EEPROM. */
|
||||
void read_MACaddr(uint8_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Sets the callback function.
|
||||
* @param callback The callback function.
|
||||
* @param userData The callback function parameter.
|
||||
*/
|
||||
void LAN91_SetCallback(lan91_callback_t callback, void *userData);
|
||||
|
||||
/** @brief Send frame from given data buffer to Lan91C111 ethernet controller. */
|
||||
bool LAN91_send_frame (uint32_t *buff, uint32_t *size );
|
||||
|
||||
/** @brief Receive frame from Lan91C111 ethernet controller to a given data buffer. */
|
||||
bool LAN91_receive_frame (uint32_t *buff, uint32_t *size );
|
||||
|
||||
/** @brief Ethernet interrupt handler. */
|
||||
void ETHERNET_Handler(void);
|
||||
|
||||
/** @brief Check Ethernet controller link status. */
|
||||
lan91_phy_status_t LAN91_GetLinkStatus(void);
|
||||
|
||||
/** @brief Output a bit value to the MII PHY management interface. */
|
||||
static void output_MDO (int bit_value);
|
||||
|
||||
/** @brief Input a bit value from the MII PHY management interface. */
|
||||
static int input_MDI (void);
|
||||
|
||||
/** @brief Write a data value to PHY register. */
|
||||
static void write_PHY (uint32_t PhyReg, int Value);
|
||||
|
||||
/** @brief Read a PHY register. */
|
||||
static uint16_t read_PHY (uint32_t PhyReg);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* inline functions
|
||||
******************************************************************************/
|
||||
|
||||
/** @brief Select Bank Register of LAN91C111 controller. */
|
||||
static inline void LAN91_SelectBank(uint8_t bank)
|
||||
{
|
||||
uint16_t current_bank = ( LREG (uint16_t, BSR) & BSR_MASK );
|
||||
if ( (bank & BSR_MASK) != current_bank )
|
||||
{
|
||||
LREG (uint16_t, BSR) = (bank & BSR_MASK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** @brief Resets the LAN91C111 controller. */
|
||||
static inline void LAN91_Reset(void)
|
||||
{
|
||||
LAN91_SelectBank(0);
|
||||
LREG (uint16_t, B0_RCR) = RCR_SOFT_RST;
|
||||
}
|
||||
|
||||
/** @brief Gets the LAN91C111 interrupt status flag. */
|
||||
static inline uint8_t LAN91_GetInterruptStatus(void)
|
||||
{
|
||||
LAN91_SelectBank(2);
|
||||
return LREG (uint8_t, B2_IST);
|
||||
}
|
||||
|
||||
/** @brief Get FIFO status if RxFIFO is empty.
|
||||
* @return ture for RxFIFO is empty, false for RxFIFO it not empty. */
|
||||
static inline bool LAN91_RxFIFOEmpty(void)
|
||||
{
|
||||
LAN91_SelectBank(2);
|
||||
return (( LREG(uint8_t, B2_IST) & IST_RCV ) == 0);
|
||||
//return (( LREG (uint16_t, B2_FIFO) & FIFO_REMPTY ) == 1);
|
||||
}
|
||||
|
||||
/** @brief Get FIFO status if TxFIFO is empty.
|
||||
* @return ture for TxFIFO is empty, false for TxFIFO it not empty. */
|
||||
static inline bool LAN91_TxFIFOEmpty(void)
|
||||
{
|
||||
LAN91_SelectBank(2);
|
||||
return (( LREG(uint8_t, B2_IST) & IST_TX_INT ) == 0);
|
||||
}
|
||||
|
||||
/** @brief Clears the Ethernet interrupt status flag. */
|
||||
static inline void LAN91_ClearInterruptMasks(void)
|
||||
{
|
||||
/* Mask off all interrupts */
|
||||
LAN91_SelectBank(2);
|
||||
LREG (uint8_t, B2_MSK) = 0;
|
||||
}
|
||||
|
||||
static inline void LAN91_SetInterruptMasks(const uint8_t mask)
|
||||
{
|
||||
/* Mask off all interrupts */
|
||||
LAN91_SelectBank(2);
|
||||
LREG (uint8_t, B2_MSK) = mask;
|
||||
}
|
||||
|
||||
static inline uint8_t LAN91_GetInterruptMasks(void)
|
||||
{
|
||||
/* Mask off all interrupts */
|
||||
LAN91_SelectBank(2);
|
||||
return (LREG (uint8_t, B2_MSK));
|
||||
}
|
||||
|
||||
/** @brief Enable Ethernet interrupt handler. */
|
||||
static inline void LAN91_SetHandler(void)
|
||||
{
|
||||
NVIC_EnableIRQ(ETHERNET_IRQn);
|
||||
}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue