moccos mizuki / EthernetXpresso

Dependents:   XNetServicesMin

Committer:
moccos
Date:
Sun May 06 11:35:17 2012 +0000
Revision:
4:7c859e671f9c
Parent:
1:95a4c234aaf6

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
moccos 0:b4bf563e9741 1 #include "LPC1769Emac.h"
moccos 0:b4bf563e9741 2 #include <LPC1768/ARM/cmsis.h>
moccos 0:b4bf563e9741 3 #include <mbed.h>
moccos 0:b4bf563e9741 4 #include "LAN8710AReg.h"
moccos 0:b4bf563e9741 5 #include "LPC1769Reg.h"
moccos 0:b4bf563e9741 6 #include "Frame.h"
moccos 0:b4bf563e9741 7
moccos 0:b4bf563e9741 8 #define BUFFER_SECTION __attribute((section("AHBSRAM1"),aligned(8)))
moccos 0:b4bf563e9741 9
moccos 0:b4bf563e9741 10 #define SET_EMAC_BIT(NAME, PATTERN) (LPC_EMAC->NAME = PATTERN}
moccos 0:b4bf563e9741 11 #define ENABLE_EMAC_BIT(NAME, MASK) (LPC_EMAC->NAME |= MASK}
moccos 0:b4bf563e9741 12 #define DISABLE_EMAC_BIT(NAME, MASK)(LPC_EMAC->NAME = LPC_EMAC->NAME & ~MASK}
moccos 0:b4bf563e9741 13
moccos 0:b4bf563e9741 14 using namespace LPC1769Reg;
moccos 0:b4bf563e9741 15
moccos 0:b4bf563e9741 16 uint8_t LPC1769Emac::mac_[6];
moccos 0:b4bf563e9741 17
moccos 0:b4bf563e9741 18 Descriptor LPC1769Emac::rx_desc_[LPC1769Emac::N_RX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 19 Descriptor LPC1769Emac::tx_desc_[LPC1769Emac::N_TX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 20 StatusRx LPC1769Emac::rx_status_[LPC1769Emac::N_RX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 21 StatusTx LPC1769Emac::tx_status_[LPC1769Emac::N_TX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 22 Frame LPC1769Emac::rx_frame_[LPC1769Emac::N_RX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 23 Frame LPC1769Emac::tx_frame_[LPC1769Emac::N_TX_BUF] BUFFER_SECTION;
moccos 0:b4bf563e9741 24
moccos 0:b4bf563e9741 25 // === inline debug function
moccos 1:95a4c234aaf6 26 #if 0
moccos 0:b4bf563e9741 27 #include "global.h"
moccos 0:b4bf563e9741 28 static inline void print_buffer(const char* title, uint8_t *buf, uint16_t size) {
moccos 0:b4bf563e9741 29 serial.printf("%s (%d bytes) dst:%02x %02x %02x %02x %02x %02x ",
moccos 0:b4bf563e9741 30 title, size, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
moccos 0:b4bf563e9741 31 buf += 6;
moccos 0:b4bf563e9741 32 serial.printf("src:%02x %02x %02x %02x %02x %02x ",
moccos 0:b4bf563e9741 33 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
moccos 0:b4bf563e9741 34 buf += 6;
moccos 0:b4bf563e9741 35 serial.printf("type:%02x %02x\r\n", buf[0], buf[1]);
moccos 0:b4bf563e9741 36 }
moccos 0:b4bf563e9741 37 #endif
moccos 0:b4bf563e9741 38
moccos 0:b4bf563e9741 39 // === public functions ===
moccos 0:b4bf563e9741 40 LPC1769Emac::LPC1769Emac() {
moccos 0:b4bf563e9741 41 // set address
moccos 0:b4bf563e9741 42 // enable ethernet block
moccos 0:b4bf563e9741 43 LPC_SC->PCONP |= 0x40000000;
moccos 0:b4bf563e9741 44
moccos 0:b4bf563e9741 45 // enable alternate functions for ethernet.
moccos 0:b4bf563e9741 46 // old values are not saved because those pins have only two functions.
moccos 0:b4bf563e9741 47 LPC_PINCON->PINSEL2 = 0x50150105;
moccos 0:b4bf563e9741 48 LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005;
moccos 0:b4bf563e9741 49 }
moccos 0:b4bf563e9741 50
moccos 0:b4bf563e9741 51 LPC1769Emac::~LPC1769Emac() {
moccos 0:b4bf563e9741 52 // TODO: disable PHY before disable ethernet block?
moccos 0:b4bf563e9741 53
moccos 0:b4bf563e9741 54 // disable alternate functions for ethernet
moccos 0:b4bf563e9741 55 LPC_PINCON->PINSEL2 = 0x00000000;
moccos 0:b4bf563e9741 56 LPC_PINCON->PINSEL3 = LPC_PINCON->PINSEL3 & ~0x0000000F;
moccos 0:b4bf563e9741 57
moccos 0:b4bf563e9741 58 // disable ethernet block
moccos 0:b4bf563e9741 59 LPC_SC->PCONP = LPC_SC->PCONP & ~0x40000000;
moccos 0:b4bf563e9741 60 }
moccos 0:b4bf563e9741 61
moccos 0:b4bf563e9741 62 bool
moccos 0:b4bf563e9741 63 LPC1769Emac::PhyWrite(uint8_t reg, uint16_t value) {
moccos 0:b4bf563e9741 64 LPC_EMAC->MADR = PHY_ADDR | reg;
moccos 0:b4bf563e9741 65 LPC_EMAC->MWTD = value;
moccos 0:b4bf563e9741 66
moccos 0:b4bf563e9741 67 uint32_t i;
moccos 0:b4bf563e9741 68 for (i = 0; i < 0x10000; i++) {
moccos 0:b4bf563e9741 69 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
moccos 0:b4bf563e9741 70 return true;
moccos 0:b4bf563e9741 71 }
moccos 0:b4bf563e9741 72 }
moccos 0:b4bf563e9741 73 return false;
moccos 0:b4bf563e9741 74 }
moccos 0:b4bf563e9741 75
moccos 0:b4bf563e9741 76 uint16_t
moccos 1:95a4c234aaf6 77 LPC1769Emac::PhyRead(uint8_t reg) {
moccos 0:b4bf563e9741 78 LPC_EMAC->MADR = PHY_ADDR | reg;
moccos 0:b4bf563e9741 79 LPC_EMAC->MCMD = MCMD_READ;
moccos 0:b4bf563e9741 80
moccos 0:b4bf563e9741 81 uint32_t i;
moccos 0:b4bf563e9741 82 for (i = 0; i < 0x10000; i++) {
moccos 0:b4bf563e9741 83 if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
moccos 0:b4bf563e9741 84 break;
moccos 0:b4bf563e9741 85 }
moccos 0:b4bf563e9741 86 }
moccos 0:b4bf563e9741 87 LPC_EMAC->MCMD = 0x0000;
moccos 0:b4bf563e9741 88
moccos 0:b4bf563e9741 89 return LPC_EMAC->MRDD;
moccos 0:b4bf563e9741 90 }
moccos 0:b4bf563e9741 91
moccos 0:b4bf563e9741 92 void
moccos 0:b4bf563e9741 93 LPC1769Emac::SetAddress(uint8_t a5, uint8_t a4, uint8_t a3, uint8_t a2, uint8_t a1, uint8_t a0) {
moccos 0:b4bf563e9741 94 mac_[5] = a0;
moccos 0:b4bf563e9741 95 mac_[4] = a1;
moccos 0:b4bf563e9741 96 mac_[3] = a2;
moccos 0:b4bf563e9741 97 mac_[2] = a3;
moccos 0:b4bf563e9741 98 mac_[1] = a4;
moccos 0:b4bf563e9741 99 mac_[0] = a5;
moccos 1:95a4c234aaf6 100 }
moccos 1:95a4c234aaf6 101
moccos 1:95a4c234aaf6 102 void
moccos 1:95a4c234aaf6 103 LPC1769Emac::UpdateAddress(uint8_t a5, uint8_t a4, uint8_t a3, uint8_t a2, uint8_t a1, uint8_t a0) {
moccos 1:95a4c234aaf6 104 mac_[5] = a0;
moccos 1:95a4c234aaf6 105 mac_[4] = a1;
moccos 1:95a4c234aaf6 106 mac_[3] = a2;
moccos 1:95a4c234aaf6 107 mac_[2] = a3;
moccos 1:95a4c234aaf6 108 mac_[1] = a4;
moccos 1:95a4c234aaf6 109 mac_[0] = a5;
moccos 1:95a4c234aaf6 110 WriteAddress_();
moccos 0:b4bf563e9741 111 }
moccos 0:b4bf563e9741 112
moccos 0:b4bf563e9741 113 void
moccos 0:b4bf563e9741 114 LPC1769Emac::StartRx() {
moccos 0:b4bf563e9741 115 LPC_EMAC->Command |= CMD_RX_EN;
moccos 0:b4bf563e9741 116 LPC_EMAC->MAC1 |= MAC1_RX_EN;
moccos 0:b4bf563e9741 117 //LPC_EMAC->IntEnable |= INT_RX_DONE;
moccos 0:b4bf563e9741 118 }
moccos 0:b4bf563e9741 119
moccos 0:b4bf563e9741 120 void
moccos 0:b4bf563e9741 121 LPC1769Emac::StartTx() {
moccos 0:b4bf563e9741 122 LPC_EMAC->Command |= CMD_TX_EN;
moccos 0:b4bf563e9741 123 //LPC_EMAC->IntEnable |= INT_TX_DONE;
moccos 0:b4bf563e9741 124 }
moccos 0:b4bf563e9741 125
moccos 0:b4bf563e9741 126 void
moccos 0:b4bf563e9741 127 LPC1769Emac::StopRx() {
moccos 0:b4bf563e9741 128 LPC_EMAC->Command = LPC_EMAC->Command & ~CMD_RX_EN;
moccos 0:b4bf563e9741 129 LPC_EMAC->MAC1 &= ~MAC1_RX_EN;
moccos 0:b4bf563e9741 130 //LPC_EMAC->IntEnable &= ~INT_RX_DONE;
moccos 0:b4bf563e9741 131 }
moccos 0:b4bf563e9741 132
moccos 0:b4bf563e9741 133 void
moccos 0:b4bf563e9741 134 LPC1769Emac::StopTx() {
moccos 0:b4bf563e9741 135 LPC_EMAC->Command = LPC_EMAC->Command & ~CMD_TX_EN;
moccos 0:b4bf563e9741 136 //LPC_EMAC->IntEnable &= ~INT_TX_DONE;
moccos 0:b4bf563e9741 137 }
moccos 0:b4bf563e9741 138
moccos 0:b4bf563e9741 139 bool
moccos 0:b4bf563e9741 140 LPC1769Emac::Link() {
moccos 0:b4bf563e9741 141 return ((PhyRead(SMIReg::BasicStatus) & SMIReg::BS_LINK) > 0);
moccos 0:b4bf563e9741 142 }
moccos 0:b4bf563e9741 143
moccos 0:b4bf563e9741 144 uint16_t
moccos 1:95a4c234aaf6 145 LPC1769Emac::Read(void *buf, uint16_t max_size) {
moccos 0:b4bf563e9741 146 uint32_t index = LPC_EMAC->RxConsumeIndex;
moccos 0:b4bf563e9741 147 if (index == LPC_EMAC->RxProduceIndex || max_size == 0) return 0;
moccos 0:b4bf563e9741 148
moccos 0:b4bf563e9741 149 uint16_t packet_size = (rx_status_[index].info & Descriptor::SIZE_MASK) + 1;
moccos 0:b4bf563e9741 150 uint16_t size = packet_size - read_size_;
moccos 0:b4bf563e9741 151 if (size > Frame::MAX_FRAME_LEN) size = Frame::MAX_FRAME_LEN;
moccos 0:b4bf563e9741 152 if (size > max_size) size = max_size;
moccos 0:b4bf563e9741 153 memcpy(buf, read_next_, size);
moccos 0:b4bf563e9741 154
moccos 0:b4bf563e9741 155 read_size_ += size;
moccos 0:b4bf563e9741 156 if (read_size_ >= packet_size) {
moccos 0:b4bf563e9741 157 // goto next buffer
moccos 0:b4bf563e9741 158 index = (index >= LPC_EMAC->RxDescriptorNumber) ? 0 : ++index;
moccos 0:b4bf563e9741 159 read_size_ = 0;
moccos 0:b4bf563e9741 160 read_next_ = rx_frame_[index].buffer;
moccos 0:b4bf563e9741 161 LPC_EMAC->RxConsumeIndex = index;
moccos 0:b4bf563e9741 162 } else {
moccos 0:b4bf563e9741 163 read_next_ += size;
moccos 0:b4bf563e9741 164 }
moccos 0:b4bf563e9741 165
moccos 0:b4bf563e9741 166 return size;
moccos 0:b4bf563e9741 167 }
moccos 0:b4bf563e9741 168
moccos 0:b4bf563e9741 169 uint16_t
moccos 0:b4bf563e9741 170 LPC1769Emac::ReadyToReceive() {
moccos 0:b4bf563e9741 171 uint32_t index = LPC_EMAC->RxConsumeIndex;
moccos 0:b4bf563e9741 172 if (index == LPC_EMAC->RxProduceIndex) return 0;
moccos 0:b4bf563e9741 173 else return (rx_status_[index].info & Descriptor::SIZE_MASK) + 1;
moccos 0:b4bf563e9741 174 }
moccos 0:b4bf563e9741 175
moccos 0:b4bf563e9741 176 uint16_t
moccos 0:b4bf563e9741 177 LPC1769Emac::Write(void *buf, uint16_t size) {
moccos 0:b4bf563e9741 178 if (size + write_size_ > Frame::MAX_FRAME_LEN) size = Frame::MAX_FRAME_LEN - write_size_;
moccos 0:b4bf563e9741 179 if (size == 0) return 0;
moccos 0:b4bf563e9741 180 uint32_t index = LPC_EMAC->TxProduceIndex;
moccos 0:b4bf563e9741 181
moccos 0:b4bf563e9741 182 memcpy(write_next_, buf, size);
moccos 0:b4bf563e9741 183 write_next_ += size;
moccos 0:b4bf563e9741 184 write_size_ += size;
moccos 0:b4bf563e9741 185 tx_desc_[index].control = (tx_desc_[index].control & (~Descriptor::SIZE_MASK)) | (size - 1);
moccos 0:b4bf563e9741 186
moccos 0:b4bf563e9741 187 return size;
moccos 0:b4bf563e9741 188 }
moccos 0:b4bf563e9741 189
moccos 0:b4bf563e9741 190 bool
moccos 0:b4bf563e9741 191 LPC1769Emac::Send() {
moccos 0:b4bf563e9741 192 if (write_size_ == 0) return true;
moccos 0:b4bf563e9741 193 uint32_t index = LPC_EMAC->TxProduceIndex;
moccos 0:b4bf563e9741 194 uint32_t index_next = (index == LPC_EMAC->TxDescriptorNumber) ? 0 : index + 1;
moccos 0:b4bf563e9741 195 if (index_next == LPC_EMAC->TxConsumeIndex) return false;
moccos 0:b4bf563e9741 196
moccos 0:b4bf563e9741 197 tx_desc_[index].control = (tx_desc_[index].control & (~Descriptor::SIZE_MASK)) | (write_size_ - 1);
moccos 0:b4bf563e9741 198 LPC_EMAC->TxProduceIndex = index_next;
moccos 0:b4bf563e9741 199 write_next_ = tx_frame_[index_next].buffer;
moccos 0:b4bf563e9741 200 write_size_ = 0;
moccos 0:b4bf563e9741 201
moccos 0:b4bf563e9741 202 return true;
moccos 0:b4bf563e9741 203 }
moccos 0:b4bf563e9741 204
moccos 0:b4bf563e9741 205 bool
moccos 0:b4bf563e9741 206 LPC1769Emac::Send(void *buf, uint16_t size) {
moccos 0:b4bf563e9741 207 write_next_ -= write_size_;
moccos 0:b4bf563e9741 208 write_size_ = 0;
moccos 0:b4bf563e9741 209 if (!Write(buf, size)) return false;
moccos 0:b4bf563e9741 210 return Send();
moccos 0:b4bf563e9741 211 }
moccos 0:b4bf563e9741 212
moccos 0:b4bf563e9741 213 bool
moccos 0:b4bf563e9741 214 LPC1769Emac::Reset(LinkMode mode) {
moccos 0:b4bf563e9741 215 bool link_100m = false;
moccos 0:b4bf563e9741 216 bool duplex_full = false;
moccos 0:b4bf563e9741 217 switch (mode) {
moccos 0:b4bf563e9741 218 case HalfDuplex10:
moccos 0:b4bf563e9741 219 break;
moccos 0:b4bf563e9741 220 case FullDuplex10:
moccos 0:b4bf563e9741 221 duplex_full = true;
moccos 0:b4bf563e9741 222 break;
moccos 0:b4bf563e9741 223 case HalfDuplex100:
moccos 0:b4bf563e9741 224 link_100m = true;
moccos 0:b4bf563e9741 225 break;
moccos 0:b4bf563e9741 226 case FullDuplex100:
moccos 0:b4bf563e9741 227 duplex_full = true;
moccos 0:b4bf563e9741 228 link_100m = true;
moccos 0:b4bf563e9741 229 break;
moccos 0:b4bf563e9741 230 case AutoNegotiate:
moccos 0:b4bf563e9741 231 duplex_full = true;
moccos 0:b4bf563e9741 232 link_100m = true;
moccos 0:b4bf563e9741 233 break;
moccos 0:b4bf563e9741 234 default:
moccos 0:b4bf563e9741 235 return false;
moccos 0:b4bf563e9741 236 }
moccos 0:b4bf563e9741 237
moccos 0:b4bf563e9741 238 // reset EMAC
moccos 0:b4bf563e9741 239 LPC_EMAC->MAC1 = MAC1_RESET_MASK;
moccos 0:b4bf563e9741 240 LPC_EMAC->Command = CMD_RESET_MASK;
moccos 0:b4bf563e9741 241 wait_us(100);
moccos 0:b4bf563e9741 242
moccos 0:b4bf563e9741 243 // emac settings
moccos 0:b4bf563e9741 244 LPC_EMAC->MCFG = MCFG_RESET_MII | MCFG_CS_DIV52; // reset MII Management
moccos 0:b4bf563e9741 245 wait_us(200);
moccos 0:b4bf563e9741 246 LPC_EMAC->MAC1 = 0x0000;
moccos 0:b4bf563e9741 247 LPC_EMAC->CLRT = CLRT_DEFAULT;
moccos 0:b4bf563e9741 248 LPC_EMAC->MAXF = Frame::MAX_FRAME_LEN;
moccos 0:b4bf563e9741 249 LPC_EMAC->IPGR = IPGR_DEFAULT;
moccos 0:b4bf563e9741 250 LPC_EMAC->MCFG = MCFG_CS_DIV52;
moccos 0:b4bf563e9741 251 if (duplex_full) {
moccos 0:b4bf563e9741 252 LPC_EMAC->MAC2 = MAC2_AUTO_PAD | MAC2_FULL_DUPLEX;
moccos 0:b4bf563e9741 253 LPC_EMAC->IPGT = IPGT_FULL_DUPLEX;
moccos 0:b4bf563e9741 254 LPC_EMAC->Command = CMD_RMII | CMD_FULL_DUPLEX;
moccos 0:b4bf563e9741 255 } else {
moccos 0:b4bf563e9741 256 LPC_EMAC->MAC2 = MAC2_AUTO_PAD;
moccos 0:b4bf563e9741 257 LPC_EMAC->IPGT = IPGT_HALF_DUPLEX;
moccos 0:b4bf563e9741 258 LPC_EMAC->Command = CMD_RMII;
moccos 0:b4bf563e9741 259 }
moccos 0:b4bf563e9741 260 LPC_EMAC->SUPP = link_100m ? SUPP_100M_MODE : 0x0000;
moccos 0:b4bf563e9741 261
moccos 0:b4bf563e9741 262 // reset PHY
moccos 0:b4bf563e9741 263 // "the reset process will be completed within 0.5s from the setting of this bit" (8710a datasheet)
moccos 0:b4bf563e9741 264 PhyWrite(SMIReg::BasicControl, SMIReg::BC_RESET);
moccos 0:b4bf563e9741 265 uint32_t i;
moccos 0:b4bf563e9741 266 bool success_flag = false;
moccos 0:b4bf563e9741 267 for (i = 0; i < 500; i++) {
moccos 0:b4bf563e9741 268 if ((PhyRead(SMIReg::BasicControl) & SMIReg::BC_RESET) == 0) { // reset bit is self-clearing
moccos 0:b4bf563e9741 269 success_flag = true;
moccos 0:b4bf563e9741 270 break;
moccos 0:b4bf563e9741 271 }
moccos 0:b4bf563e9741 272 wait_ms(1);
moccos 0:b4bf563e9741 273 }
moccos 0:b4bf563e9741 274 if (!success_flag) return false; // failed to reset
moccos 0:b4bf563e9741 275
moccos 0:b4bf563e9741 276 // why 100M settings fail??
moccos 0:b4bf563e9741 277 switch (mode) {
moccos 0:b4bf563e9741 278 case HalfDuplex10:
moccos 0:b4bf563e9741 279 PhyWrite(SMIReg::BasicControl, 0x0000);
moccos 0:b4bf563e9741 280 break;
moccos 0:b4bf563e9741 281 case FullDuplex10:
moccos 0:b4bf563e9741 282 PhyWrite(SMIReg::BasicControl, SMIReg::BC_FULL_DUPLEX);
moccos 0:b4bf563e9741 283 break;
moccos 0:b4bf563e9741 284 case HalfDuplex100:
moccos 0:b4bf563e9741 285 PhyWrite(SMIReg::BasicControl, SMIReg::BC_100M);
moccos 0:b4bf563e9741 286 break;
moccos 0:b4bf563e9741 287 case FullDuplex100:
moccos 0:b4bf563e9741 288 PhyWrite(SMIReg::BasicControl, SMIReg::BC_FULL_DUPLEX | SMIReg::BC_100M);
moccos 0:b4bf563e9741 289 break;
moccos 0:b4bf563e9741 290 case AutoNegotiate:
moccos 0:b4bf563e9741 291 PhyWrite(SMIReg::BasicControl, SMIReg::BC_AUTONEG);
moccos 0:b4bf563e9741 292 // CheckAutoNeg_();
moccos 0:b4bf563e9741 293 break;
moccos 0:b4bf563e9741 294 default:
moccos 0:b4bf563e9741 295 return false;
moccos 0:b4bf563e9741 296 }
moccos 0:b4bf563e9741 297
moccos 0:b4bf563e9741 298 InitRxBuffer_();
moccos 0:b4bf563e9741 299 InitTxBuffer_();
moccos 0:b4bf563e9741 300 WriteAddress_();
moccos 0:b4bf563e9741 301
moccos 0:b4bf563e9741 302
moccos 0:b4bf563e9741 303 LPC_EMAC->IntClear = INT_ALL_MASK;
moccos 0:b4bf563e9741 304 LPC_EMAC->RxFilterCtrl = RXFC_BCAST | RXFC_PERFECT;
moccos 0:b4bf563e9741 305
moccos 0:b4bf563e9741 306 return true;
moccos 0:b4bf563e9741 307 }
moccos 0:b4bf563e9741 308
moccos 0:b4bf563e9741 309 // === private functions ===
moccos 0:b4bf563e9741 310 void
moccos 0:b4bf563e9741 311 LPC1769Emac::WriteAddress_() {
moccos 0:b4bf563e9741 312 LPC_EMAC->SA0 = ((uint16_t)mac_[5] << 8) | mac_[4];
moccos 0:b4bf563e9741 313 LPC_EMAC->SA1 = ((uint16_t)mac_[3] << 8) | mac_[2];
moccos 0:b4bf563e9741 314 LPC_EMAC->SA2 = ((uint16_t)mac_[1] << 8) | mac_[0];
moccos 0:b4bf563e9741 315 }
moccos 0:b4bf563e9741 316
moccos 0:b4bf563e9741 317 // currently not used
moccos 0:b4bf563e9741 318 bool
moccos 0:b4bf563e9741 319 LPC1769Emac::CheckAutoNeg_() {
moccos 0:b4bf563e9741 320 bool success_flag = false;
moccos 0:b4bf563e9741 321 uint32_t i, r;
moccos 0:b4bf563e9741 322 for (i = 0; i < 0x10000; i++) {
moccos 0:b4bf563e9741 323 r = PhyRead(SMIReg::BasicStatus);
moccos 0:b4bf563e9741 324 if (r & SMIReg::BS_AUTONEG_COMPLETE) {
moccos 0:b4bf563e9741 325 success_flag = true;
moccos 0:b4bf563e9741 326 break;
moccos 0:b4bf563e9741 327 }
moccos 0:b4bf563e9741 328 }
moccos 0:b4bf563e9741 329 if (!success_flag) return false;
moccos 0:b4bf563e9741 330
moccos 0:b4bf563e9741 331 r = PhyRead(SMIReg::PHYSpecialControlStatus);
moccos 0:b4bf563e9741 332
moccos 0:b4bf563e9741 333 // update regs
moccos 0:b4bf563e9741 334 bool link_100m = ((r & SMIReg::SP_100M) > 0);
moccos 0:b4bf563e9741 335 bool duplex_full = ((r & SMIReg::SP_FULL_DUPLEX) > 0);
moccos 0:b4bf563e9741 336
moccos 0:b4bf563e9741 337 if (duplex_full) {
moccos 0:b4bf563e9741 338 LPC_EMAC->MAC2 = MAC2_AUTO_PAD | MAC2_FULL_DUPLEX;
moccos 0:b4bf563e9741 339 LPC_EMAC->IPGT = IPGT_FULL_DUPLEX;
moccos 0:b4bf563e9741 340 LPC_EMAC->Command = CMD_RMII | CMD_FULL_DUPLEX;
moccos 0:b4bf563e9741 341 } else {
moccos 0:b4bf563e9741 342 LPC_EMAC->MAC2 = MAC2_AUTO_PAD;
moccos 0:b4bf563e9741 343 LPC_EMAC->IPGT = IPGT_HALF_DUPLEX;
moccos 0:b4bf563e9741 344 LPC_EMAC->Command = CMD_RMII;
moccos 0:b4bf563e9741 345 }
moccos 0:b4bf563e9741 346 LPC_EMAC->SUPP = link_100m ? SUPP_100M_MODE : 0x0000;
moccos 0:b4bf563e9741 347
moccos 0:b4bf563e9741 348 return true;
moccos 0:b4bf563e9741 349 }
moccos 0:b4bf563e9741 350
moccos 0:b4bf563e9741 351 void
moccos 0:b4bf563e9741 352 LPC1769Emac::InitRxBuffer_() {
moccos 0:b4bf563e9741 353 uint16_t i;
moccos 0:b4bf563e9741 354
moccos 0:b4bf563e9741 355 // set initial descriptor
moccos 0:b4bf563e9741 356 for (i = 0; i < N_RX_BUF; i++) {
moccos 0:b4bf563e9741 357 rx_desc_[i].packet = (uint32_t)&rx_frame_[i];
moccos 0:b4bf563e9741 358 rx_desc_[i].control = 0x80000000 | (Frame::MAX_FRAME_LEN - 1);
moccos 0:b4bf563e9741 359 }
moccos 0:b4bf563e9741 360
moccos 0:b4bf563e9741 361 // emac registers
moccos 0:b4bf563e9741 362 LPC_EMAC->RxDescriptor = (uint32_t)rx_desc_;
moccos 0:b4bf563e9741 363 LPC_EMAC->RxStatus = (uint32_t)rx_status_;
moccos 0:b4bf563e9741 364 LPC_EMAC->RxDescriptorNumber = N_RX_BUF - 1; // this register is minus one encoded
moccos 0:b4bf563e9741 365 LPC_EMAC->RxConsumeIndex = 0;
moccos 0:b4bf563e9741 366 read_next_ = rx_frame_[0].buffer;
moccos 0:b4bf563e9741 367 read_size_ = 0;
moccos 0:b4bf563e9741 368 }
moccos 0:b4bf563e9741 369
moccos 0:b4bf563e9741 370 void
moccos 0:b4bf563e9741 371 LPC1769Emac::InitTxBuffer_() {
moccos 0:b4bf563e9741 372 uint16_t i;
moccos 0:b4bf563e9741 373
moccos 0:b4bf563e9741 374 // set initial descriptor
moccos 0:b4bf563e9741 375 for (i = 0; i < N_TX_BUF; i++) {
moccos 0:b4bf563e9741 376 tx_desc_[i].packet = (uint32_t)&tx_frame_[i];
moccos 0:b4bf563e9741 377 tx_desc_[i].control = 0xf4000000 | Frame::MAX_FRAME_LEN;
moccos 0:b4bf563e9741 378 tx_status_[i].info = 0;
moccos 0:b4bf563e9741 379 }
moccos 0:b4bf563e9741 380
moccos 0:b4bf563e9741 381 // emac registers
moccos 0:b4bf563e9741 382 LPC_EMAC->TxDescriptor = (uint32_t)tx_desc_;
moccos 0:b4bf563e9741 383 LPC_EMAC->TxStatus = (uint32_t)tx_status_;
moccos 0:b4bf563e9741 384 LPC_EMAC->TxDescriptorNumber = N_TX_BUF - 1; // this register is minus one encoded
moccos 0:b4bf563e9741 385 LPC_EMAC->TxProduceIndex = 0;
moccos 0:b4bf563e9741 386 write_next_ = tx_frame_[0].buffer;
moccos 0:b4bf563e9741 387 write_size_ = 0;
moccos 0:b4bf563e9741 388 }