embkernel
 All Classes Functions Variables Typedefs Groups Pages
NetMac.cpp
1 //------------------------------------------------------------------------------
2 //This file is part of embKernel.
3 //See license.txt for the full license governing this code.
4 //------------------------------------------------------------------------------
5 
6 #include "RtosInclude.hpp"
7 #include "Net.hpp"
8 #include "NetMac.hpp"
9 #include "LibEndian.hpp"
10 #include "NetDefs.hpp"
11 #include "RtosInterrupt.hpp"
12 #include "NetMacros.hpp"
13 #include "stm32f4xx.h"
14 #include <string.h>
15 
16 NetMac::NetMac() :
17  mSema(1, 1) {
18 }
19 
20 void NetMac::start(const NetDefs::MAC_ADDR& addr) {
21  sAddr = addr;
22 
23  RtosPortable::disableAllInt();
24 
25  RCC ->AHB1ENR |= RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN | //
26  RCC_AHB1ENR_ETHMACRXEN;
27 
28  RCC ->AHB1RSTR |= RCC_AHB1RSTR_ETHMACRST;
29  RCC ->AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST;
30 
31  RtosPortable::enableAllInt();
32 
33  ETH ->DMABMR |= ETH_DMABMR_SR;
34  while (ETH ->DMABMR & ETH_DMABMR_SR ) {
36  }
37 
38  ETH ->MACMIIAR &= ((uint32_t) 0xFFFFFFE3);
39  ETH ->MACMIIAR |= ETH_MACMIIAR_CR_Div102;
40 
42 
43  mPhyAddr = 0;
44 
45  mPhyId = phyRead(PHY_REG_IDR1) << 16;
46  mPhyId += phyRead(PHY_REG_IDR2);
47 
48  //Reset the device
49  phyWrite(PHY_REG_BMCR, PHY_BMCR_RESET);
50 
51  // Wait for hardware reset to end
52  for (int i = 500; i; i--) {
53  uint32_t reg = phyRead(PHY_REG_BMCR);
54  if (!((reg) & (PHY_BMCR_RESET | PHY_BMCR_POWERDOWN))) {
55  break;
56  }
58  }
59 
60  // Set PHY mode AUTO
61  phyWrite(PHY_REG_BMCR, PHY_BMCR_AN);
62 
63  for (int i = 500; i; i--) {
64  if (phyRead(PHY_REG_BMSR) & PHY_BMSR_AUTO_DONE) {
65  break;
66  }
68  }
69 
70  //Check the link status.
71  for (int i = 500; i; i--) {
72  uint32_t reg = phyRead(PHY_REG_BMSR);
73  if (reg & PHY_BMSR_LINK_ESTABLISHED) {
74  break;
75  }
77  }
78 
79  ETH ->MACA0HR = (addr.v[5] << 8) + (addr.v[4]);
80  ETH ->MACA0LR = (addr.v[3] << 24) + (addr.v[2] << 16) + (addr.v[1] << 8) + (addr.v[0]);
81 
82  //init tx descriptors
83  memset(sTxDesc, 0, sizeof(sTxDesc));
84  for (int i = 0; i < EMAC_TX_FRAG_COUNT; i++) {
85  sTxDesc[i].tdes0.value = TX_DESC0_TCH;
86  sTxDesc[i].tdes1.value = 0;
87  sTxDesc[i].tdes2 = 0;
88  sTxDesc[i].tdes3 = (uint32_t) &sTxDesc[(i + 1) % EMAC_TX_FRAG_COUNT];
89  sTxDesc[i].state = TX_FRAG_STATE::TX_FRAG_NO_BUFFER;
90  }
91  sTxNextToSend = 0;
92  sTxNextToCheck = 0;
93  ETH ->DMATDLAR = (uint32_t) sTxDesc;
94 
95  //init rx descriptors
96  memset(sRxDesc, 0, sizeof(sRxDesc));
97  for (int i = 0; i < EMAC_RX_FRAG_COUNT; i++) {
98  sRxDesc[i].rdes0.value = RX_DESC0_OWN;
99  sRxDesc[i].rdes1.bits.RCH = 1;
100  sRxDesc[i].rdes1.bits.RBS1 = NetDefs::MAX_FRAME_LEN + 2;
101  sRxDesc[i].rdes2 = (uint32_t) &Net::allocFrame(NetDefs::MAX_FRAME_LEN + 4)->types.mac.macHeader.dstAddr;
102  sRxDesc[i].rdes3 = (uint32_t) &sRxDesc[(i + 1) % EMAC_RX_FRAG_COUNT];
103  }
104  ETH ->DMARDLAR = (uint32_t) sRxDesc;
105  mRxIdx = 0;
106 
107  ETH ->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_RIE | ETH_DMAIER_TIE;
108 
109  NVIC ->IP[ETH_IRQn] = RTOS_INT_PRI;
110  NVIC_EnableIRQ(ETH_IRQn);
111 
112  //MAC configuration register
113  ETH ->MACCR |= ETH_MACCR_DM | ETH_MACCR_FES;
114  //MAC frame filter register
115  ETH ->MACFFR = ETH_MACFFR_PCF_BlockAll;
116  //MAC hash table high register
117  ETH ->MACHTHR = 0;
118  //MAC hash table low register
119  ETH ->MACHTLR = 0;
120  //MAC flow control register
121  ETH ->MACFCR = ETH_MACFCR_ZQPD;
122  //MAC VLAN tag register
123  ETH ->MACVLANTR = 0;
124  //DMA operation mode register
125  ETH ->DMAOMR = ETH_DMAOMR_RSF | ETH_DMAOMR_TSF | ETH_DMAOMR_OSF;
126  //DMA bus mode register
127  ETH ->DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_USP | ETH_DMABMR_PBL_32Beat | ETH_DMABMR_FB | ETH_DMABMR_RDP_32Beat | ETH_DMABMR_RTPR_2_1;
128  //Enable transmit state machine
129  ETH ->MACCR |= ETH_MACCR_TE;
130  // Set the Flush Transmit FIFO bit
131  ETH ->DMAOMR |= ETH_DMAOMR_FTF;
132  // Enable the MAC reception
133  ETH ->MACCR |= ETH_MACCR_RE;
134  // Enable the DMA transmission
135  ETH ->DMAOMR |= ETH_DMAOMR_ST;
136  // Enable the DMA reception
137  ETH ->DMAOMR |= ETH_DMAOMR_SR;
138 }
139 
140 NetDefs::FRAME* NetMac::getFrame() {
141  if (!sRxDesc[mRxIdx].rdes0.bits.OWN) {
142  if (!sRxDesc[mRxIdx].rdes0.bits.LS) {
143  sRxDesc[mRxIdx].rdes0.value = RX_DESC0_OWN;
144  do {
145  mRxIdx = (mRxIdx + 1) % EMAC_RX_FRAG_COUNT;
146  if (sRxDesc[mRxIdx].rdes0.bits.OWN) {
147  break;
148  }
149  sRxDesc[mRxIdx].rdes0.value = RX_DESC0_OWN;
150  if (sRxDesc[mRxIdx].rdes0.bits.LS) {
151  break;
152  }
153  } while (true);
154  return ((NetDefs::FRAME*) 0);
155  }
156  if (sRxDesc[mRxIdx].rdes0.bits.ES) {
157  sRxDesc[mRxIdx].rdes0.value = RX_DESC0_OWN;
158  mRxIdx = (mRxIdx + 1) % EMAC_RX_FRAG_COUNT;
159  return ((NetDefs::FRAME*) 0);
160  }
161  NetDefs::FRAME* newFrame = Net::allocFrame(NetDefs::MAX_FRAME_LEN + 4);
162  if (!newFrame) {
163  sRxDesc[mRxIdx].rdes0.value = RX_DESC0_OWN;
164  mRxIdx = (mRxIdx + 1) % EMAC_RX_FRAG_COUNT;
165  return ((NetDefs::FRAME*) 0);
166  }
167  NetDefs::FRAME* frame = (NetDefs::FRAME*) (sRxDesc[mRxIdx].rdes2 - 2);
168  frame = (NetDefs::FRAME*) Net::resizeFrame(*frame, sRxDesc[mRxIdx].rdes0.bits.FL + 2);
169  sRxDesc[mRxIdx].rdes2 = (uint32_t) &newFrame->types.mac.macHeader.dstAddr;
170  sRxDesc[mRxIdx].rdes0.value = RX_DESC0_OWN;
171  mRxIdx = (mRxIdx + 1) % EMAC_RX_FRAG_COUNT;
172  frame->types.mac.macHeader.type = (NetDefs::MAC_TYPE) LibEndian::beToHw((uint16_t) frame->types.mac.macHeader.type);
173  return frame;
174  }
175  return ((NetDefs::FRAME*) 0);
176 }
177 
178 void NetMac::putHeader(NetDefs::FRAME& frame, const NetDefs::MAC_ADDR& dst, NetDefs::MAC_TYPE type) {
179  frame.types.mac.macHeader.dstAddr = dst;
180  frame.types.mac.macHeader.srcAddr = sAddr;
181  frame.types.mac.macHeader.type = (NetDefs::MAC_TYPE) LibEndian::hwToBe((uint16_t) type);
182 }
183 
184 bool NetMac::flush(NetDefs::FRAME& frame, size_t len, bool discardable) {
185  if (len <= 0) {
186  Net::freeFrame(frame);
187  return false;
188  }
189 
190  mSema.take(Rtos::TICK_INFINITE);
191 
192  TX_DESC* desc = &sTxDesc[sTxNextToSend];
193  if (desc->state != TX_FRAG_STATE::TX_FRAG_NO_BUFFER) {
194  if (discardable) {
195  Net::freeFrame(frame);
196  }
197  mSema.give(Rtos::TICK_INFINITE);
198  return false;
199  }
200 
201  desc->tdes1.bits.TBS1 = sizeof(NetDefs::MAC_HEADER) - 2 + len;
202  desc->tdes2 = (uint32_t) &frame.types.mac.macHeader.dstAddr;
203 
204  if (discardable) {
205  desc->state = TX_FRAG_STATE::TX_FRAG_DISCARDABLE;
206  }
207  else {
208  desc->state = TX_FRAG_STATE::TX_FRAG_NOT_DISCARDABLE;
209  }
210 
211  desc->tdes0.value = TX_DESC0_OWN | TX_DESC0_IC | TX_DESC0_FS | TX_DESC0_LS | TX_DESC0_TCH;
212  sTxNextToSend = (sTxNextToSend + 1) % EMAC_TX_FRAG_COUNT;
213 
214  if (ETH ->DMASR & ETH_DMASR_TBUS ) {
215  ETH ->DMASR = ETH_DMASR_TBUS;
216  }
217  ETH ->DMATPDR = 0;
218 
219  mSema.give(Rtos::TICK_INFINITE);
220  return true;
221 }
222 
223 void NetMac::freeSentFrames() {
224  while (true) {
225  TX_DESC* desc = &sTxDesc[sTxNextToCheck];
226 
227  if (desc->state == TX_FRAG_STATE::TX_FRAG_NO_BUFFER) {
228  return;
229  }
230  if (desc->tdes0.bits.OWN) {
231  return;
232  }
233  if (desc->state == TX_FRAG_STATE::TX_FRAG_DISCARDABLE) {
234  Net::freeFrame(*((NetDefs::FRAME*) (desc->tdes2 - 2)));
235  }
236  desc->state = TX_FRAG_STATE::TX_FRAG_NO_BUFFER;
237  sTxNextToCheck = (sTxNextToCheck + 1) % EMAC_TX_FRAG_COUNT;
238  }
239 
240 }
241 
242 #define EMAC_DEF_PHY_REG 0x0001
243 #define EMAC_DEF_CLOCK_RANGE 0x0004
244 
245 bool NetMac::phyWrite(uint16_t reg, uint16_t value) {
246  ETH ->MACMIIDR = value;
247  ETH ->MACMIIAR = (mPhyAddr << 11) | EMAC_DEF_CLOCK_RANGE | reg << 6 | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
249  while (true) {
250  if (Rtos::isElapsed(timeout)) {
251  return false;
252  }
253  if (!(ETH ->MACMIIAR & ETH_MACMIIAR_MB )) {
254  return true;
255  }
256  Rtos::sleep(1);
257  }
258 }
259 
260 uint32_t NetMac::phyRead(uint16_t reg) {
261  ETH ->MACMIIAR = (mPhyAddr << 11) | EMAC_DEF_CLOCK_RANGE | reg << 6 | ETH_MACMIIAR_MB;
263  while (true) {
264  if (Rtos::isElapsed(timeout)) {
265  return -1;
266  }
267  if (!(ETH ->MACMIIAR & ETH_MACMIIAR_MB )) {
268  return ETH ->MACMIIDR;
269  }
270  Rtos::sleep(1);
271  }
272 }
273 
274 void RtosInterrupt::IRQ_ETH() {
275  uint32_t mask = ETH ->DMASR;
276  ETH ->DMASR = mask;
277  if ((mask & ETH_DMASR_TS )|| (mask & ETH_DMASR_RS)){
278  if(!Net::onMacEventInterrupt()) {
279  Rtos::nop();
280  }
281 }
282 }
283