Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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