moccos mizuki / EthernetXpresso

Dependents:   XNetServicesMin

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