EMAC32 - Operational Overview
Contents
The following sections summarize initialization of the EMAC32 Controller and the steps involved in sending and receiving messages. A section is also included which summarizes the steps required to write to, or read from, the internal PHY device registers.
Initializing the RX and TX Buffers
The EMAC32 can handle RX and TX buffers of any size, as long as each is located in a 1MB address 'window'. This means, in practical terms, that the maximum size of the RX and TX buffers is 1MB. This 1MB window is defined by the most significant 12 bits of the start address register in each case (RX_START and TX_START), and provides the base address for the respective buffer in memory. Bits 19..2 in each start address register defines an offset from the base address to the actual start of the buffer.
The following code fragments illustrate how the buffer initialization is performed.
In the hardware.h
file:
#define Base_EMAC_RAM 0x02000000
#define Size_EMAC_RAM 0x00008000
In the main.c
file:
int8_t emac_rx_buffer[0x5000] __at( Base_EMAC_RAM );
int8_t emac_tx_buffer[0x3000] __at( Base_EMAC_RAM + sizeof(emac_rx_buffer));
Initializing the Controller
You will need to re-initialize the Controller, ready for reception of messages, after each reset – either the result of receiving an external (hardware) reset on the WBS_RST_I input, or a software reset initiated by writing the rst
bit in either the RX_CMD, TX_CMD, or PHY_CMD registers. Initialization of the Controller involves:
- Writing the 48-bit MAC Address for the Controller to the RX_MAC1 and RX_MAC2 registers.
- Writing the RX_START register with the start address of the Receive Buffer.
- Writing the RX_END register with the end address of the Receive Buffer.
- Writing the RX_INPUT and RX_OUTPUT registers with the start address of the Receive Buffer.
- Writing the TX_START register with the start address of the Transmit Buffer.
- Writing the TX_END register with the end address of the Transmit Buffer.
- Writing the TX_INPUT and TX_OUTPUT registers with the start address of the Transmit Buffer.
- Starting the Receiver by setting the bit(s) for the desired mode(s) – Promiscuous (
pr
), Multicast (mc
), Broadcast (bc
), Unicast (uc
) – and theen
bit, in the RX_CMD register.
- Enabling the Transmitter by setting the desired mode (half/full duplex) – using the
fd
bit – and setting theen
bit, in the TX_CMD register.
The following code fragments illustrate how the Controller initialization is performed.
In the main.c
file:
emac32_init( Base_EMAC, mac, EMAC_RX_MODE, EMAC_TX_MODE, RX_IE_OVERFLOW, 0,
emac_rx_buffer, sizeof(emac_rx_buffer),
emac_tx_buffer, sizeof(emac_tx_buffer) );
This is a call to the initialization function in the emac32.c
file:
void emac32_init( uint32_t base, const t_mac_addr mac_addr, uint32_t
rx_mode, uint32_t tx_mode, uint32_t rx_int, uint32_t
tx_int, int8_t* rx_buf, int32_t rx_buf_size, int8_t*
tx_buf, int32_t tx_buf_size )
{
// reset EMAC
RX_CMD_REG(base) = RX_SOFT_RST;
TX_CMD_REG(base) = TX_SOFT_RST;
MDI_CMD_REG(base) = MDI_SOFT_RST;
RX_CMD_REG(base) = 0;
TX_CMD_REG(base) = 0;
MDI_CMD_REG(base) = 0;
// write MAC address into the Individual Address Registers
RX_MAC_REG1(base) = *(int32_t*)mac_addr;
RX_MAC_REG2(base) = (int32_t)*(int16_t*)&mac_addr[4];
// write local mac address
memcpy(mymac, mac_addr, 6);
// set external buffer registers
RX_START_REG(base) = (int32_t)rx_buf;
RX_END_REG(base) = (int32_t)rx_buf + rx_buf_size;
RX_INPUT_REG(base) = (int32_t)rx_buf;
RX_OUTPUT_REG(base) = (int32_t)rx_buf;
TX_START_REG(base) = (int32_t)tx_buf;
TX_END_REG(base) = (int32_t)tx_buf + tx_buf_size;
TX_INPUT_REG(base) = (int32_t)tx_buf;
TX_OUTPUT_REG(base) = (int32_t)tx_buf;
RX_INT_REG(base) = rx_int;
TX_INT_REG(base) = tx_int;
RX_CMD_REG(base) = rx_mode;
TX_CMD_REG(base) = tx_mode;
}
With regard to the end, input and output registers for the Receiver and Transmitter, there is no need to write bits 31..20, which is a concatenated copy of the base address. There is no penalty for doing so however, as these bits will just be ignored (bits 31..20 cannot be overwritten).
Transmitting a Message
To send a message to the connected PHY device:
- Read the TX_INPUT and TX_OUTPUT registers to see if there is space for the next message:
- If TX_OUTPUT is lower than TX_INPUT, see if there is enough space behind the TX_INPUT address. If so, write the length of the packet to the location pointed to by TX_INPUT, followed by the packet itself. Update TX_INPUT with the first address behind the end of the packet which is on a boundary of 4.
- If there was not enough space behind the TX_INPUT address, check if there is enough space between the start of the buffer and the TX_OUTPUT address. If so, write
00000000h
(4byte) to the location pointed to by the TX_INPUT address, write the packet length and the packet at the beginning of the buffer and update TX_INPUT with the first address behind the end of the packet which is on a boundary of 4. - If TX_INPUT is lower than TX_OUTPUT see if there is enough space between both pointers and write the packet length and packet data and update TX_INPUT as above.
- The Transmitter will send the packet and update the TX_OUTPUT automatically.
When reading the TX_START, TX_END, TX_INPUT, or TX_OUTPUT registers, the full buffer address is returned – including the base address (bits 31..20).
The Controller will construct the frame for the message, in accordance with the Ethernet protocol. If configured in Half-Duplex Mode, the Controller will listen to see whether it can transmit – by monitoring its PHY_CRS input. Provided this input is Low, there is no current activity on the Ethernet bus and transmission can go ahead. Transmission is carried out, one nibble at a time, from the PHY_TXD output on each rising edge of the transmit clock provided by the PHY device (arriving at the PHY_TXC input).
When the Controller has completed the transmission, the PHY_TXEN signal will go Low. An interrupt can be generated to alert the host processor that the Transmitter has sent a packet. Simply enable the associated interrupt by setting the efs
bit in the TX_INT register. When this interrupt is generated, the corresponding ifs
flag in the TX_STATUS register will go High and an active interrupt output at the WBS_INT_O pin of the device will be generated. The interrupt can be cleared by writing a '1' to the ifs
bit in the TX_STATUS register, or by issuing a hardware or software reset of the device.
Receiving a Message
To receive a message that has been transmitted from the connected PHY device to the EMAC32 Controller:
- Read the RX_INPUT and RX_OUTPUT registers. If RX_OUTPUT is not equal to RX_INPUT, there are packets waiting in the Receive Buffer.
- Read the length of the packet at the address the RX_OUTPUT register is pointing to. If this length is
00000000h
, start reading at the beginning of the Receive Buffer.
- Read the packet from the Receive Buffer.
- Update the RX_OUTPUT register to the first address behind the end of the packet which is on a boundary of 4. This frees the space used by the packet and make it available to the Receiver again.
When reading the RX_START, RX_END, RX_INPUT, or RX_OUTPUT registers, the full buffer address is returned – including the base address (bits 31..20).
Depending on the mode the Receiver is in, the Receiver can receive the following packets:
- Unicast: The destination MAC address has to be exactly the same as the address in the RX_MAC2:RXMAC1 register.
- Broadcast: The destination MAC address consists of all '1's.
- Multicast: The destination MAC address has the multicast bit set (bit 0).
- Promiscuous: All packets are received, irrespective of the destination MAC address.
When the Receiver has completed reception of a message frame, the PHY_RXDV signal will go Low. An interrupt can be generated to alert the host processor that the Receiver has received a packet. Simply enable the associated interrupt by setting the efo
bit in the RX_INT register. When this interrupt is generated, the corresponding ifo
flag in the RX_STATUS register will go High and an active interrupt output at the WBS_INT_O pin of the device will be generated. The interrupt can be cleared by writing a '1' to the ifo
bit in the RX_STATUS register, or by issuing a hardware or software reset of the device.
Communicating with Internal PHY Registers
The following two sections detail how to write to and read from, an internal register in the connected PHY device.
Only one action – Read or Write – can be started at a time. If you give the command to both write to and read from, an internal PHY register, the read command will be accepted and proceed, while the write command will be ignored.
Writing to a PHY Register
To write to an internal register of the PHY device:
- Read the PHY_CMD register. If the MD interface is ready for another action all bits in this register will be '0'. This check is an important one, as writing to either of the address registers (PHY_ADDR, REG_ADDR) or the data register (PHY_DAT) while a command is pending can give unexpected results
- Write the address of the PHY Controller device to the PHY_ADDR register
- Write the address of the internal PHY register that you wish to write to, to the REG_ADDR register
- Write the data that you wish to send to the addressed internal PHY register, into the PHY_DAT register
- Start the Write command by setting the
rwr
bit of the PHY_CMD register (PHY_CMD.0).
At the end of the transmission, the rwr
bit in the PHY_CMD register will go Low, signifying that the write action is complete and the MD interface is ready for the next operation.
Reading from a PHY Register
To read from an internal register of the PHY device:
- Read the PHY_CMD register. If the MD interface is ready for another action all bits in this register will be '0'. This check is an important one, as writing to either of the address registers (PHY_ADDR, REG_ADDR) while a command is pending can give unexpected results
- Write the address of the PHY Controller device to the PHY_ADDR register
- Write the address of the internal PHY register that you wish to read from, to the REG_ADDR register
- Start the Read command by setting the
rrd
bit of the PHY_CMD register (PHY_CMD.1).
At the end of the reception, the rrd
bit in the PHY_CMD register will go Low, signifying that the read action is complete and the MD interface is ready for the next operation. Read the data received from the addressed internal PHY register, from the PHY_DAT register.