Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NanostackEMACInterface.cpp Source File

NanostackEMACInterface.cpp

00001 /*
00002  * Copyright (c) 2017 ARM Limited. All rights reserved.
00003  */
00004 
00005 #include "NanostackEthernetInterface.h"
00006 #include "NanostackEthernetPhy.h"
00007 #include "nsdynmemLIB.h"
00008 #include "arm_hal_phy.h"
00009 #include "EMAC.h"
00010 
00011 class EMACPhy : public NanostackEthernetPhy
00012 {
00013 public:
00014     EMACPhy(NanostackMemoryManager &mem, EMAC &m);
00015     virtual int8_t phy_register();
00016     virtual void get_mac_address(uint8_t *mac);
00017     virtual void set_mac_address(uint8_t *mac);
00018 
00019     int8_t address_write(phy_address_type_e , uint8_t *);
00020     int8_t tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle,data_protocol_e data_flow);
00021 
00022     void emac_phy_rx(emac_mem_buf_t *mem);
00023 
00024 private:
00025     NanostackMemoryManager &memory_manager;
00026     EMAC &emac;
00027     uint8_t mac_addr[6];
00028     int8_t device_id;
00029     phy_device_driver_s phy;
00030 };
00031 
00032 // GAH! no handles on the callback. Force a single interface
00033 static EMACPhy *single_phy;
00034 
00035 extern "C"
00036 {
00037 static int8_t emac_phy_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
00038 {
00039     return single_phy->address_write(address_type, address_ptr);
00040 }
00041 
00042 static int8_t emac_phy_interface_state_control(phy_interface_state_e, uint8_t)
00043 {
00044     return -1;
00045 }
00046 
00047 static int8_t emac_phy_tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle,data_protocol_e data_flow)
00048 {
00049     return single_phy->tx(data_ptr, data_len, tx_handle, data_flow);
00050 }
00051 
00052 EMACPhy::EMACPhy(NanostackMemoryManager &mem, EMAC &m) : memory_manager(mem), emac(m), device_id(-1)
00053 {
00054     /* Same default address logic as lwIP glue uses */
00055 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
00056     mac_addr[0] = MBED_MAC_ADDR_0;
00057     mac_addr[1] = MBED_MAC_ADDR_1;
00058     mac_addr[2] = MBED_MAC_ADDR_2;
00059     mac_addr[3] = MBED_MAC_ADDR_3;
00060     mac_addr[4] = MBED_MAC_ADDR_4;
00061     mac_addr[5] = MBED_MAC_ADDR_5;
00062 #else
00063     mbed_mac_address((char *) mac_addr);
00064 #endif
00065     /* We have a default MAC address, so do don't force them to supply one */
00066     /* They may or may not update hwaddr with their address */
00067     emac.get_hwaddr(mac_addr);
00068 }
00069 
00070 
00071 void EMACPhy::emac_phy_rx(emac_mem_buf_t *mem)
00072 {
00073     const uint8_t *ptr = NULL;
00074     uint8_t *tmpbuf = NULL;
00075     uint32_t total_len;
00076 
00077     if (memory_manager.get_next(mem) == NULL) {
00078         // Easy contiguous case
00079         ptr = static_cast<const uint8_t*>(memory_manager.get_ptr(mem));
00080         total_len = memory_manager.get_len(mem);
00081     } else {
00082         // Nanostack can't accept chunked data - make temporary contiguous copy
00083         total_len = memory_manager.get_total_len(mem);
00084         ptr = tmpbuf = static_cast<uint8_t *>(ns_dyn_mem_temporary_alloc(total_len));
00085         if (tmpbuf) {
00086             memory_manager.copy_from_buf(tmpbuf, total_len, mem);
00087         }
00088     }
00089 
00090     if (ptr && phy.phy_rx_cb) {
00091         phy.phy_rx_cb(ptr, total_len, 0xff, 0, device_id);
00092     }
00093     ns_dyn_mem_free(tmpbuf);
00094     memory_manager.free(mem);
00095 }
00096 
00097 } // extern "C"
00098 
00099 int8_t EMACPhy::address_write(phy_address_type_e address_type, uint8_t *address_ptr)
00100 {
00101     if (address_type != PHY_MAC_48BIT) {
00102         return -1;
00103     }
00104     memcpy(mac_addr, address_ptr, 6);
00105     emac.set_hwaddr(address_ptr);
00106     return 0;
00107 }
00108 
00109 int8_t EMACPhy::tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle,data_protocol_e data_flow)
00110 {
00111     emac_mem_buf_t *mem = memory_manager.alloc_pool(data_len, 0);
00112     if (!mem) {
00113         return -1;
00114     }
00115     memory_manager.copy_to_buf(mem, data_ptr, data_len);
00116 
00117     // They take ownership - their responsibility to free
00118     emac.link_out(mem);
00119 
00120     return 0;
00121 }
00122 
00123 int8_t EMACPhy::phy_register()
00124 {
00125     if (device_id < 0) {
00126 
00127         phy.PHY_MAC = mac_addr;
00128         phy.address_write = emac_phy_address_write;
00129         phy.driver_description = const_cast<char*>("ETH");
00130         phy.link_type = PHY_LINK_ETHERNET_TYPE;
00131         phy.phy_MTU = 0;
00132         phy.phy_header_length = 0;
00133         phy.phy_tail_length = 0;
00134         phy.state_control = emac_phy_interface_state_control;
00135         phy.tx = emac_phy_tx;
00136         phy.phy_rx_cb = NULL;
00137         phy.phy_tx_done_cb = NULL;
00138 
00139         emac.set_memory_manager(memory_manager);
00140         emac.set_link_input_cb(mbed::callback(this, &EMACPhy::emac_phy_rx));
00141 
00142         if (!emac.power_up()) {
00143             return -1;
00144         }
00145 
00146         phy.phy_MTU = emac.get_mtu_size();
00147         /* Set the address - this could be either board default, what they
00148          * told us with EMAC::get_mac_address, or something manually specified
00149          * with EMACPhy::set_mac_address
00150          */
00151         emac.set_hwaddr(mac_addr);
00152 
00153         emac.set_all_multicast(true);
00154 
00155         device_id = arm_net_phy_register(&phy);
00156        // driver_readiness_status_callback = driver_status_cb;
00157 
00158         if (device_id < 0){
00159             //tr_error("Ethernet Driver failed to register with Stack. RetCode=%i", eth_driver_enabled);
00160             //driver_readiness_status_callback(0, eth_interface_id);
00161             emac.power_down();
00162             return -1;
00163         }
00164     }
00165 
00166     return device_id;
00167 }
00168 
00169 void EMACPhy::get_mac_address(uint8_t *mac)
00170 {
00171     memcpy(mac, mac_addr, sizeof mac_addr);
00172 }
00173 
00174 void EMACPhy::set_mac_address(uint8_t *mac)
00175 {
00176     memcpy(mac_addr, mac, sizeof mac_addr);
00177 }
00178 
00179 nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, Nanostack::EthernetInterface **interface_out, const uint8_t *mac_addr)
00180 {
00181     if (single_phy) {
00182         return NSAPI_ERROR_DEVICE_ERROR ;
00183     }
00184 
00185     single_phy = new (std::nothrow) EMACPhy(this->memory_manager, emac);
00186     if (!single_phy) {
00187         return NSAPI_ERROR_NO_MEMORY ;
00188     }
00189 
00190     if (mac_addr) {
00191         single_phy->set_mac_address(const_cast<uint8_t*>(mac_addr));
00192     }
00193 
00194     Nanostack::EthernetInterface *interface;
00195 
00196     interface = new (std::nothrow) Nanostack::EthernetInterface(*single_phy);
00197     if (!interface) {
00198         return NSAPI_ERROR_NO_MEMORY ;
00199     }
00200 
00201     nsapi_error_t err = interface->initialize();
00202     if (err) {
00203         delete interface;
00204         return err;
00205     }
00206 
00207     *interface_out = interface;
00208 
00209     return NSAPI_ERROR_OK ;
00210 
00211 }
00212 
00213 nsapi_error_t Nanostack::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
00214 {
00215     Nanostack::EthernetInterface *interface;
00216     nsapi_error_t err = add_ethernet_interface(emac, default_if, &interface);
00217     *interface_out = interface;
00218     return err;
00219 }