diff --git a/connectivity/drivers/emac/README.md b/connectivity/drivers/emac/README.md new file mode 100644 index 0000000..fc3361a --- /dev/null +++ b/connectivity/drivers/emac/README.md @@ -0,0 +1,185 @@ +# mbed OS Ethernet MAC (EMAC) drivers + +This document describes how to port and test an Ethernet MAC (EMAC) driver to +mbed OS. It is based on work on the feature-emac branch as of mbed OS 5.8, +which is intended to be merged into mbed OS 5.9 + +The scope of this document is limited to Ethernet (IEEE 802.3) or Ethernet-like +devices such as Wi-Fi (IEEE 802.11), where the device presents a MAC interface +to send and receive frames, and this will be used by one of the onboard +network stacks that runs on mbed OS on the host processor. + +(If the device has an off-board network stack, a driver would need to implement +`NetworkStack` directly instead to pass network calls to that offboard +stack). + +## Abstractions + +The EMAC interface is designed to abstract network stacks and drivers, and to +easily permit multiple instances. The key API classes are: + +* `NetworkInterface` - an mbed OS network interface of any type +* `NetworkStack` - an mbed OS network stack of any type (may be off-board) +* `OnboardNetworkStack` - an on-board network stack +* `EMAC` - an Ethernet MAC device driver +* `EMACMemoryManager` - a memory manager used to pass data between driver and stack +* `EMACInterface`- a `NetworkInterface` that uses an `EMAC` driver and an `OnboardNetworkStack` + +## The EMAC driver core + +The first step in the port is to create a driver class that can be instantiated +to control your device. This must be derived from class `EMAC`. +This API is used by a network stack (or test framework) to control your driver. + +The EMAC-derived driver would normally be installed in +connectivity/drivers/emac/targets, often in a `TARGET_XXX` directory. + +Class EMAC is entirely abstract - you need to implement about a dozen calls +to activate the driver, send and receive packets, and perform other control +and information functions. + +There are also callback registration functions for upcalls from the driver - the +stack can register callback functions for packet reception and link status +changes. + + +## The EMAC memory manager + +For the send and receive paths, data is transferred in memory buffers controlled +via an `EMACMemoryManager` object. The network stack using an EMAC driver +provides it with a reference to the memory manager in use before powering up - +this will be constant as long as the EMAC is powered up. + +On the output call, the EMAC driver is given ownership of a buffer chain - it +must free the chain when it has finished with the data. The data may or may +not be contiguous. A driver can express alignment preferences for outgoing data, +but the network stack is not required to meet these prefernces, so a driver +relying on alignment may need a slow path that copies data into an aligned +(or contiguous) buffer. + +For reception, the EMAC driver must allocate memory from the `EMACMemoryManager` +to store the received packets - this is then passed to the link input callback, +which will free it. By preference this memory should be allocated using the pool, +but if contiguous memory is required it can be allocated from the heap. + + +## EthernetInterface + +If your driver is a pure Ethernet driver, there is no further implementation +required. The class `EthernetInterface` can use any `EMAC` driver to provide +an mbed OS `NetworkInterface`: + + MyEMAC my_emac(params); + EthernetInterface net(&my_emac); + + net.connect(); + +This will attach the default network stack (normally lwIP - the other +current alternative is Nanostack) to the specified EMAC driver, and provide all +the generic `NetworkInterface` and `NetworkStack` APIs. + +## Being the default EMAC / EthernetInterface + +To make your EMAC the default for applications you should define the static function +`EMAC::get_default_instance()` to return an instance of your emac, eg: + + MBED_WEAK EMAC &EMAC::get_default_instance() + { + static MyEMAC my_emac(params); + return &my_emac; + } + +This permits this example application code to work: + + EthernetInterface net; // uses EMAC::get_default_instance() + net.connect(); + +This definition would normally be gated by a target label of some sort. As +target code, your definition of EMAC::get_default_instance() must be weak - +this permits it to be overridden by application code. + +## Wi-Fi interfaces + +As a Wi-Fi interface, a little more work is required - at a minimum you need +to implement the extra configuration calls in `WiFiInterface`. This +is because the network stacks and EMAC APIs are only related to the +Ethernet-like data path - they have no knowledge of any other configuration +mechanisms and assume they are already set up. + +To do this, you should create a C++ class that inherits from both +`WiFiInterface` and `EMACInterface`. The `EMACInterface` is a helper class +that implements all the core `NetworkInterface` functionality for you. You +then just need to implement the extra `WiFiInterface` configuration methods. + +For reference, note that `EthernetInterface` also derives from +`EMACInterface`, but has no extra code as there is no extra configuration +required. + +As a Wi-fi driver, you will not normally be directly exposing your `EMAC` class - +it would not normally be declared as `EMAC::get_default_instance`, but you +would pass it to the constructor of your base `EMACInterface`. This then +will make it visible via the `get_emac` method. This is for test purposes, +meaning the test framework can do: + + MyWiFiInterface net; + net.set_credentials(); + EMAC &emac = net.get_emac(); + do_emac_test(emac); + +This must work in your driver - it must be possible to power up and use the +built-in EMAC directly without the `NetworkInterface::connect()` method being +invoked, as long as the credentials have been set. This structure will come naturally if +you just use the default `EMACInterface::connect()` implementation. + +Note also that your constructor must allow the network stack to be specified using +the same form as `EthernetInterface`: + + MyWiFiInterface(OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); + +## OnboardNetworkStack + +The precise details of the `OnboardNetworkStack` API should not concern +an EMAC driver writer - it provides the mechanism to bind a driver to a stack, and +the APIs needed to implement a `NetworkInterface`, but this is handled by +`EMACInterface`, either as a base class of your own `XXXInterface` or as +the base of `EthernetInterface`. + +## DEVICE_EMAC + +At present, as an interim measure, targets providing `EMAC::get_default_instance()` +should add "EMAC" in `device_has` in their `targets.json`. This activates +network tests in CI builds. + +This is subject to change, but is necessary in lieu of the previous typical +behaviour of gating tests on `FEATURE_LWIP`. + +## Tuning memory allocations + +Depending on its use of pool and heap memory, and other factors, a driver might +want to tune the configuration of particular network stacks. This can be done via +the `mbed_lib.json` of each network stack, using their `target_overrides` +section. + +## Testing + +The mbed OS tree contains Greentea-based tests that exercise the EMAC API +directly, and more general socket tests. + +See here for general Greentea information: + +See here for the emac tests: + + +Greentea socket tests are at: + + +The driver should also be exercised with real-world examples like + + +The driver should also be tested with both network stacks available in mbed OS, +as they will use the driver somewhat differently - try with the JSON option +`nsapi.default-stack` set to each of `LWIP` and `NANOSTACK`. + +Nanostack is IPv6 only. IPv6 operation should also be tested with lwIP, as this +is likely to reveal problems with multicast filtering that may not be spotted +by IPv4 or Nanostack. diff --git a/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp b/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp new file mode 100644 index 0000000..95ec2bf --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp @@ -0,0 +1,319 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" +#include "fvp_emac.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +using namespace std::chrono; + +/******************************************************************************** + * Internal data + ********************************************************************************/ + +#define THREAD_STACKSIZE 512 + +/* Flags for worker thread */ +#define FLAG_TX (0x1u << 0) +#define FLAG_RX (0x1u << 1) + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityNormal) + +#define PHY_TASK_PERIOD 200ms + + +fvp_EMAC::fvp_EMAC() : _thread(THREAD_PRIORITY, THREAD_STACKSIZE, NULL, "fvp_emac_thread") + +{ +} + +void fvp_EMAC::ethernet_callback(lan91_event_t event, void *param) +{ + fvp_EMAC *enet = static_cast(param); + switch (event) { + case LAN91_RxEvent: + enet->rx_isr(); + break; + case LAN91_TxEvent: + enet->tx_isr(); + break; + default: + break; + } +} + +/** \brief Ethernet receive interrupt handler */ +void fvp_EMAC::rx_isr() +{ + _thread.flags_set(FLAG_RX); +} + +/** \brief Ethernet transmit interrupt handler */ +void fvp_EMAC::tx_isr() +{ + _thread.flags_set(FLAG_TX); +} + +/** \brief Low level init of the MAC and PHY. */ +bool fvp_EMAC::low_level_init_successful() +{ + LAN91_init(); + LAN91_SetCallback(&fvp_EMAC::ethernet_callback, this); + return true; +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void fvp_EMAC::thread_function(void *pvParameters) +{ + struct fvp_EMAC *fvp_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = ThisThread::flags_wait_any(FLAG_RX | FLAG_TX); + if (flags & FLAG_RX) { + fvp_enet->packet_rx(); + } + } +} + + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + */ +void fvp_EMAC::packet_rx() +{ + while (!LAN91_RxFIFOEmpty()) { + emac_mem_buf_t *temp_rxbuf = NULL; + uint32_t *rx_payload_ptr; + uint32_t rx_length = 0; + + temp_rxbuf = _memory_manager->alloc_heap(FVP_ETH_MAX_FLEN, LAN91_BUFF_ALIGNMENT); + + /* no memory been allocated*/ + if (NULL != temp_rxbuf) { + + rx_payload_ptr = (uint32_t *)_memory_manager->get_ptr(temp_rxbuf); + rx_length = _memory_manager->get_len(temp_rxbuf); + bool state; + +#ifdef LOCK_RX_THREAD + /* Get exclusive access */ + _TXLockMutex.lock(); +#endif + state = LAN91_receive_frame(rx_payload_ptr, &rx_length); + +#ifdef LOCK_RX_THREAD + _TXLockMutex.unlock(); +#endif + if (!state) { + _memory_manager->free(temp_rxbuf); + continue; + } else { + _memory_manager->set_len(temp_rxbuf, rx_length); + } + _emac_link_input_cb(temp_rxbuf); + } + } + LAN91_SetInterruptMasks(MSK_RCV); +} + + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +bool fvp_EMAC::link_out(emac_mem_buf_t *buf) +{ + // If buffer is chained or not aligned then make a contiguous aligned copy of it + if (_memory_manager->get_next(buf) || + reinterpret_cast(_memory_manager->get_ptr(buf)) % LAN91_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = _memory_manager->alloc_heap(_memory_manager->get_total_len(buf), LAN91_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + _memory_manager->free(buf); + return false; + } + + // Copy to new buffer and free original + _memory_manager->copy(copy_buf, buf); + _memory_manager->free(buf); + buf = copy_buf; + } + + /* Save the buffer so that it can be freed when transmit is done */ + uint32_t *buffer; + uint32_t tx_length = 0; + bool state; + buffer = (uint32_t *)(_memory_manager->get_ptr(buf)); + tx_length = _memory_manager->get_len(buf); + + /* Get exclusive access */ + _TXLockMutex.lock(); + + /* Setup transfers */ + state = LAN91_send_frame(buffer, &tx_length); + _TXLockMutex.unlock(); + /* Restore access */ + + + if (!state) { + return false; + } + /* Free the buffer */ + _memory_manager->free(buf); + + return true; +} + +/** \brief PHY task monitoring the link */ +void fvp_EMAC::phy_task() +{ + // Get current status + lan91_phy_status_t connection_status; + connection_status = LAN91_GetLinkStatus(); + + if (connection_status != _prev_state && _emac_link_state_cb) { + _emac_link_state_cb(connection_status); + } + _prev_state = connection_status; +} + +bool fvp_EMAC::power_up() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + /* Start ethernet Worker thread */ + _thread.start(callback(&fvp_EMAC::thread_function, this)); + + /* Trigger thread to deal with any RX packets that arrived before thread was started */ + rx_isr(); + + /* PHY monitoring task */ + _prev_state = STATE_LINK_DOWN; + + mbed::mbed_event_queue()->call(mbed::callback(this, &fvp_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + ThisThread::sleep_for(10); + + _phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &fvp_EMAC::phy_task)); + + return true; +} + +uint32_t fvp_EMAC::get_mtu_size() const +{ + return LAN91_ETH_MTU_SIZE; +} + +uint32_t fvp_EMAC::get_align_preference() const +{ + return LAN91_BUFF_ALIGNMENT; +} + +void fvp_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, FVP_ETH_IF_NAME, (size < sizeof(FVP_ETH_IF_NAME)) ? size : sizeof(FVP_ETH_IF_NAME)); +} + +uint8_t fvp_EMAC::get_hwaddr_size() const +{ + return FVP_HWADDR_SIZE; +} + +bool fvp_EMAC::get_hwaddr(uint8_t *addr) const +{ + read_MACaddr(addr); + return true; +} + +void fvp_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void fvp_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + _emac_link_input_cb = input_cb; +} + +void fvp_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + _emac_link_state_cb = state_cb; +} + +void fvp_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void fvp_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void fvp_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void fvp_EMAC::power_down() +{ + /* No-op at this stage */ +} + +void fvp_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + _memory_manager = &mem_mngr; +} + + +fvp_EMAC &fvp_EMAC::get_instance() +{ + static fvp_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return fvp_EMAC::get_instance(); +} + +/** @} */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h b/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h new file mode 100644 index 0000000..7f74007 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h @@ -0,0 +1,178 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FVP_EMAC_H_ +#define FVP_EMAC_H_ + +#include "EMAC.h" +#include "mbed.h" +#include "rtos/Mutex.h" +#include "lan91c111.h" + + +#define FVP_HWADDR_SIZE (6) +#define FVP_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame +#define FVP_ETH_IF_NAME "ARM0" + +class fvp_EMAC : public EMAC { +public: + fvp_EMAC(); + + static fvp_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + bool low_level_init_successful(); + void rx_isr(); + void tx_isr(); + void packet_rx(); + static void thread_function(void *pvParameters); + void phy_task(); + static void ethernet_callback(lan91_event_t event, void *param); + + Thread _thread; /* Processing thread */ + rtos::Mutex _TXLockMutex; /* TX critical section mutex */ + + emac_link_input_cb_t _emac_link_input_cb; /* Callback for incoming data */ + emac_link_state_change_cb_t _emac_link_state_cb; /* Link state change callback */ + + EMACMemoryManager *_memory_manager; /* Memory manager */ + + int _phy_task_handle; /* Handle for phy task event */ + lan91_phy_status_t _prev_state; +}; + +#endif /* FVP_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json new file mode 100644 index 0000000..d54a278 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json @@ -0,0 +1,7 @@ +{ + "name": "smsc9220-emac", + "config": { + "rx-ring-len": 1, + "tx-ring-len": 1 + } +} diff --git a/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp new file mode 100644 index 0000000..ca97bc6 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "mbed_interface.h" +#include "mbed_wait_api.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +#include "smsc9220_emac.h" +#include "smsc9220_eth_drv.h" + +#ifndef SMSC9220_ETH +#error "SMSC9220_ETH should be defined, check device_cfg.h!" +#endif + +#ifndef SMSC9220_Ethernet_Interrupt_Handler +#error "SMSC9220_Ethernet_Interrupt_Handler should be defined to platform's \ +Ethernet IRQ handler!" +#endif + +static SMSC9220_EMAC *board_emac_pointer = NULL; +const struct smsc9220_eth_dev_t* SMSC9220_EMAC::dev = &SMSC9220_ETH_DEV; + +extern "C" void SMSC9220_Ethernet_Interrupt_Handler(void) +{ + if (smsc9220_get_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL)) { + board_emac_pointer->rx_isr(); + smsc9220_clear_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + smsc9220_disable_interrupt(SMSC9220_EMAC::dev, + SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + } +} + +SMSC9220_EMAC::SMSC9220_EMAC() : receiver_thread(LINK_STATUS_THREAD_PRIORITY, + (uint32_t)LINK_STATUS_THREAD_STACKSIZE) +{ +} + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt. + */ +void SMSC9220_EMAC::rx_isr() +{ + receiver_thread.flags_set(FLAG_RX); +} + +/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming + * packet. + * + * \return a emac_mem_buf_t filled with the received packet + * (including MAC header) + */ +emac_mem_buf_t *SMSC9220_EMAC::low_level_input() +{ + emac_mem_buf_t *p = NULL; + uint32_t message_length = 0; + uint32_t received_bytes = 0; + + message_length = smsc9220_peek_next_packet_size(dev); + if (message_length == 0) { + return p; + } else { + /* The Ethernet controller cannot remove CRC from the end of the + * incoming packet, thus it should be taken into account when + * calculating the actual message length.*/ + message_length -= CRC_LENGTH_BYTES; + } + + p = _memory_manager->alloc_heap(SMSC9220_ETH_MAX_FRAME_SIZE, + SMSC9220_BUFF_ALIGNMENT); + + if (p != NULL) { + _RXLockMutex.lock(); + received_bytes = smsc9220_receive_by_chunks(dev, + (char*)_memory_manager->get_ptr(p), + _memory_manager->get_len(p)); + if(received_bytes == 0){ + _memory_manager->free(p); + p = nullptr; + } else { + _memory_manager->set_len(p, received_bytes); + } + _RXLockMutex.unlock(); + } + + return p; +} + +/** \brief Receiver thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] params pointer to the interface data + */ +void SMSC9220_EMAC::receiver_thread_function(void* params) +{ + struct SMSC9220_EMAC *smsc9220_enet = static_cast(params); + + while(1) { + uint32_t flags = ThisThread::flags_wait_any(FLAG_RX); + + if (flags & FLAG_RX) { + smsc9220_enet->packet_rx(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the Network Stack. + */ +void SMSC9220_EMAC::packet_rx() +{ + emac_mem_buf_t *p; + p = low_level_input(); + if(p != NULL) { + _emac_link_input_cb(p); + } + smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); +} + +bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf) +{ + if(buf == NULL) { + return false; + } else { + uint32_t buffer_chain_length = 0; + enum smsc9220_error_t error = SMSC9220_ERROR_NONE; + /* If buffer is chained or not aligned then + * make a contiguous aligned copy of it */ + if (_memory_manager->get_next(buf) || + reinterpret_cast(_memory_manager->get_ptr(buf)) % + SMSC9220_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = _memory_manager->alloc_heap( + _memory_manager->get_total_len(buf), + SMSC9220_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + _memory_manager->free(buf); + return false; + } + + /* Copy to new buffer and free original */ + _memory_manager->copy(copy_buf, buf); + _memory_manager->free(buf); + buf = copy_buf; + } + + buffer_chain_length = _memory_manager->get_total_len(buf); + + _TXLockMutex.lock(); + error = smsc9220_send_by_chunks(dev, + buffer_chain_length, + true, + (const char*)_memory_manager->get_ptr(buf), + _memory_manager->get_len(buf)); + _memory_manager->free(buf); + _TXLockMutex.unlock(); + return (error == SMSC9220_ERROR_NONE); + } +} + +void SMSC9220_EMAC::link_status_task() +{ + uint32_t phy_basic_status_reg_value = 0; + bool current_link_status_up = false; + + /* Get current status */ + smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BSTATUS, + &phy_basic_status_reg_value); + + current_link_status_up = (bool)(phy_basic_status_reg_value & + (1ul << (PHY_REG_BSTATUS_LINK_STATUS_INDEX))); + + /* Compare with the previous state */ + if (current_link_status_up != _prev_link_status_up) { + _emac_link_state_cb(current_link_status_up); + _prev_link_status_up = current_link_status_up; + } + +} + +bool SMSC9220_EMAC::power_up() +{ + board_emac_pointer = this; + receiver_thread.start(callback(&SMSC9220_EMAC::receiver_thread_function, + this)); + + /* Initialize the hardware */ + enum smsc9220_error_t init_successful = smsc9220_init(dev, &ThisThread::sleep_for); + if (init_successful != SMSC9220_ERROR_NONE) { + return false; + } + + /* Init FIFO level interrupts: use Rx status level irq to trigger + * interrupts for any non-processed packets, while Tx is not irq driven */ + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); + smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS, + SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX); + + /* Enable Ethernet interrupts in NVIC */ + NVIC_EnableIRQ(ETHERNET_IRQn); + smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); + + /* Trigger thread to deal with any RX packets that arrived + * before receiver_thread was started */ + rx_isr(); + _prev_link_status_up = PHY_STATE_LINK_DOWN; + mbed::mbed_event_queue()->call(mbed::callback(this, + &SMSC9220_EMAC::link_status_task)); + + /* Allow the Link Status task to detect the initial link state */ + ThisThread::sleep_for(10); + _link_status_task_handle = mbed::mbed_event_queue()->call_every( + LINK_STATUS_TASK_PERIOD_MS, + mbed::callback(this, + &SMSC9220_EMAC::link_status_task)); + + return true; +} + +uint32_t SMSC9220_EMAC::get_mtu_size() const +{ + return SMSC9220_ETH_MTU_SIZE; +} + +uint32_t SMSC9220_EMAC::get_align_preference() const +{ + return SMSC9220_BUFF_ALIGNMENT; +} + +void SMSC9220_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, SMSC9220_ETH_IF_NAME, (size < sizeof(SMSC9220_ETH_IF_NAME)) ? + size : sizeof(SMSC9220_ETH_IF_NAME)); +} + +uint8_t SMSC9220_EMAC::get_hwaddr_size() const +{ + return SMSC9220_HWADDR_SIZE; +} + +bool SMSC9220_EMAC::get_hwaddr(uint8_t *addr) const +{ + if(smsc9220_read_mac_address(dev, (char*)addr) == SMSC9220_ERROR_NONE) { + return true; + } else { + return false; + } +} + +void SMSC9220_EMAC::set_hwaddr(const uint8_t *addr) +{ + if (!addr) { + return; + } + + memcpy(_hwaddr, addr, sizeof _hwaddr); + uint32_t mac_low = 0; + uint32_t mac_high = 0; + + /* Using local variables to make sure the right alignment is used */ + memcpy((void*)&mac_low, (void*)addr, 4); + memcpy((void*)&mac_high, (void*)(addr+4), 2); + + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRL, mac_low)) { + return; + } + if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, mac_high)) { + return; + } +} + +void SMSC9220_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + _emac_link_input_cb = input_cb; +} + +void SMSC9220_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + _emac_link_state_cb = state_cb; +} + +void SMSC9220_EMAC::add_multicast_group(const uint8_t *addr) +{ + // No action for now +} + +void SMSC9220_EMAC::remove_multicast_group(const uint8_t *addr) +{ + // No action for now +} + +void SMSC9220_EMAC::set_all_multicast(bool all) +{ + // No action for now +} + +void SMSC9220_EMAC::power_down() +{ + // No action for now +} + +void SMSC9220_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + _memory_manager = &mem_mngr; +} + + +SMSC9220_EMAC &SMSC9220_EMAC::get_instance() { + static SMSC9220_EMAC emac; + return emac; +} + +/* Weak so a module can override */ +MBED_WEAK EMAC &EMAC::get_default_instance() { + return SMSC9220_EMAC::get_instance(); +} diff --git a/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h new file mode 100644 index 0000000..58762d4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMSC9220_EMAC_H_ +#define SMSC9220_EMAC_H_ + +#include "EMAC.h" +#include "mbed.h" +#include "rtos/Mutex.h" + +#include "smsc9220_emac_config.h" + +class SMSC9220_EMAC : public EMAC { +public: + SMSC9220_EMAC(); + + static SMSC9220_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may + * or may not align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct + * size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own + * HW address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is + * provided the stack would normally use that, but it could be overridden, + * eg for test purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that + * interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given + * interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + void rx_isr(); + + static const struct smsc9220_eth_dev_t *dev; + +private: + void packet_rx(); + void link_status_task(); + bool low_level_init_successful(); + emac_mem_buf_t *low_level_input(); + static void receiver_thread_function(void* params); + + rtos::Mutex _TXLockMutex; + rtos::Mutex _RXLockMutex; + bool _prev_link_status_up; + int _link_status_task_handle; + uint8_t _hwaddr[SMSC9220_HWADDR_SIZE]; + + Thread receiver_thread; + EMACMemoryManager *_memory_manager; + emac_link_input_cb_t _emac_link_input_cb; + emac_link_state_change_cb_t _emac_link_state_cb; + +}; + +#endif /* SMSC9220_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h new file mode 100644 index 0000000..93d73f4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SMSC9220_EMAC_CONFIG_H +#define SMSC9220_EMAC_CONFIG_H + +#include "cmsis_os.h" + +#define SMSC9220_HWADDR_SIZE 6U +#define SMSC9220_BUFF_ALIGNMENT 4U + +/* + * Maximum Transfer Unit + * The IEEE 802.3 specification limits the data portion of the 802.3 frame + * to a minimum of 46 and a maximum of 1522 bytes, this is on L2 level. + */ +#define SMSC9220_ETH_MTU_SIZE 1500U +#define SMSC9220_ETH_IF_NAME "smsc9220" +#define SMSC9220_ETH_MAX_FRAME_SIZE 1522U + +/** \brief Defines for receiver thread */ +#define FLAG_RX 1U +#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal) +#define LINK_STATUS_THREAD_STACKSIZE 512U +#define LINK_STATUS_TASK_PERIOD_MS 200U +#define PHY_STATE_LINK_DOWN false +#define PHY_STATE_LINK_UP true +#define CRC_LENGTH_BYTES 4U + +#endif /* SMSC9220_EMAC_CONFIG_H */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp new file mode 100644 index 0000000..1fefdee --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp @@ -0,0 +1,349 @@ +/* + * Copyright 2018-2020 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "SclSTAInterface.h" +#include "nsapi.h" +#include "lwipopts.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "rtos.h" +#include "scl_emac.h" +#include "scl_ipc.h" +#include "mbed_wait_api.h" + + +/** @file + * Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects + */ +#define MIN_SSID_LENGTH (0) +#define MIN_PASSWORD_LENGTH (0) + +struct scl_tx_net_credentials { + nsapi_security_t network_security_type; + int ssid_len; + int pass_len; + const char *network_ssid; + const char *network_passphrase; +} scl_tx_network_credentials; + +network_params_t network_parameter; + +int scl_toerror(scl_result_t res) +{ + switch (res) { + case SCL_SUCCESS: + return NSAPI_ERROR_OK; + case SCL_UNSUPPORTED: + return NSAPI_ERROR_UNSUPPORTED; + case SCL_BADARG: + return NSAPI_ERROR_PARAMETER; + case SCL_INVALID_JOIN_STATUS: + return NSAPI_ERROR_NO_CONNECTION; + case SCL_BUFFER_UNAVAILABLE_PERMANENT: + case SCL_BUFFER_UNAVAILABLE_TEMPORARY: + case SCL_RX_BUFFER_ALLOC_FAIL: + case SCL_BUFFER_ALLOC_FAIL: + case SCL_MALLOC_FAILURE: + return NSAPI_ERROR_NO_MEMORY; + case SCL_ACCESS_POINT_NOT_FOUND: + case SCL_NETWORK_NOT_FOUND: + return NSAPI_ERROR_NO_SSID; + case SCL_NOT_AUTHENTICATED: + case SCL_INVALID_KEY: + case SCL_NOT_KEYED: + return NSAPI_ERROR_AUTH_FAILURE; + case SCL_PENDING: + case SCL_JOIN_IN_PROGRESS: + return NSAPI_ERROR_IN_PROGRESS; + case SCL_CONNECTION_LOST: + return NSAPI_ERROR_CONNECTION_LOST; + case SCL_TIMEOUT: + case SCL_EAPOL_KEY_PACKET_M1_TIMEOUT: + case SCL_EAPOL_KEY_PACKET_M3_TIMEOUT: + case SCL_EAPOL_KEY_PACKET_G1_TIMEOUT: + return NSAPI_ERROR_CONNECTION_TIMEOUT; + default: + return -res; + } +} + +nsapi_security_t scl_tosecurity(scl_security_t sec) +{ + switch (sec) { + case SCL_SECURITY_OPEN: + return NSAPI_SECURITY_NONE; + case SCL_SECURITY_WEP_PSK: + case SCL_SECURITY_WEP_SHARED: + return NSAPI_SECURITY_WEP; + case SCL_SECURITY_WPA_TKIP_PSK: + case SCL_SECURITY_WPA_TKIP_ENT: + return NSAPI_SECURITY_WPA; + case SCL_SECURITY_WPA2_MIXED_PSK: + return NSAPI_SECURITY_WPA_WPA2; + case SCL_SECURITY_WPA2_AES_PSK: + case SCL_SECURITY_WPA2_AES_ENT: + case SCL_SECURITY_WPA2_FBT_PSK: + case SCL_SECURITY_WPA2_FBT_ENT: + return NSAPI_SECURITY_WPA2; + default: + return NSAPI_SECURITY_UNKNOWN; + } +} + +scl_security_t scl_fromsecurity(nsapi_security_t sec) +{ + switch (sec) { + case NSAPI_SECURITY_NONE: + return SCL_SECURITY_OPEN; + case NSAPI_SECURITY_WEP: + return SCL_SECURITY_WEP_PSK; + case NSAPI_SECURITY_WPA: + return SCL_SECURITY_WPA_MIXED_PSK; + case NSAPI_SECURITY_WPA2: + return SCL_SECURITY_WPA2_AES_PSK; + case NSAPI_SECURITY_WPA_WPA2: + return SCL_SECURITY_WPA2_MIXED_PSK; + default: + return SCL_SECURITY_UNKNOWN; + } +} + +SclSTAInterface::SclSTAInterface(SCL_EMAC &emac, OnboardNetworkStack &stack) + : EMACInterface(emac, stack), + _ssid("\0"), + _pass("\0"), + _security(NSAPI_SECURITY_NONE), + _scl_emac(emac) +{ +} + +nsapi_error_t SclSTAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel) +{ + int err = set_channel(channel); + if (err) { + return err; + } + + err = set_credentials(ssid, pass, security); + if (err) { + return err; + } + + return connect(); +} + +nsapi_error_t SclSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) +{ + if ((ssid == NULL) || + (strlen(ssid) == 0) || + (pass == NULL && (security != NSAPI_SECURITY_NONE)) || + (strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE)) || + (strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA || security == NSAPI_SECURITY_WPA_WPA2)) + ) { + return NSAPI_ERROR_PARAMETER; + } + + memset(_ssid, 0, sizeof(_ssid)); + strncpy(_ssid, ssid, sizeof(_ssid)); + + memset(_pass, 0, sizeof(_pass)); + strncpy(_pass, pass, sizeof(_pass)); + + _security = security; + + return NSAPI_ERROR_OK; +} + +nsapi_error_t SclSTAInterface::connect() +{ + + uint32_t delay_timeout = 0; + scl_result_t ret_val; + nsapi_error_t interface_status; + uint32_t connection_status = 0; + + scl_tx_network_credentials.network_ssid = _ssid; + if ((strlen(_ssid) < MAX_SSID_LENGTH) && (strlen(_ssid) > MIN_SSID_LENGTH)) { + scl_tx_network_credentials.ssid_len = strlen(_ssid); + } else { + return NSAPI_ERROR_PARAMETER; + } + scl_tx_network_credentials.network_passphrase = _pass; + if (((strlen(_pass) < MAX_PASSWORD_LENGTH) && (strlen(_pass) > MIN_PASSWORD_LENGTH)) || (_security == NSAPI_SECURITY_NONE)) { + scl_tx_network_credentials.pass_len = strlen(_pass); + } else { + return NSAPI_ERROR_PARAMETER; + } + scl_tx_network_credentials.network_security_type = _security; + + ret_val = scl_send_data(SCL_TX_CONNECT, (char *)&scl_tx_network_credentials, TIMER_DEFAULT_VALUE); + + if (ret_val == SCL_SUCCESS) { + SCL_LOG(("wifi provisioning in progress\r\n")); + } + + network_parameter.connection_status = NSAPI_STATUS_DISCONNECTED; + + + //Get the network parameter from NP + while ((network_parameter.connection_status != NSAPI_STATUS_GLOBAL_UP) && delay_timeout < NW_CONNECT_TIMEOUT) { + ret_val = scl_get_nw_parameters(&network_parameter); + wait_us(NW_DELAY_TIME_US); + delay_timeout++; + } + + if (delay_timeout >= NW_CONNECT_TIMEOUT || ret_val != SCL_SUCCESS) { + return NSAPI_ERROR_NO_CONNECTION; + } + + if (!_scl_emac.powered_up) { + _scl_emac.power_up(); + } + + if (!_interface) { + nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + } + + if (!scl_wifi_is_ready_to_transceive()) { + scl_emac_wifi_link_state_changed(true); + } + + interface_status = _interface->bringup(false, + network_parameter.ip_address, + network_parameter.netmask, + network_parameter.gateway, + DEFAULT_STACK); + + if (interface_status == NSAPI_ERROR_OK) { + scl_send_data(SCL_TX_CONNECTION_STATUS, (char *)&connection_status, TIMER_DEFAULT_VALUE); + } + + return interface_status; +} + +void SclSTAInterface::wifi_on() +{ + if (!_scl_emac.powered_up) { + _scl_emac.power_up(); + } +} + +nsapi_error_t SclSTAInterface::disconnect() +{ + scl_result_t ret_val; + nsapi_error_t disconnect_status; + uint32_t delay_timeout = 0; + + ret_val = scl_send_data(SCL_TX_DISCONNECT, (char *)&disconnect_status, TIMER_DEFAULT_VALUE); + + if (ret_val == SCL_ERROR) { + return NSAPI_ERROR_TIMEOUT; + } + + if (!_interface) { + return NSAPI_ERROR_NO_CONNECTION; + } + + // block till disconnected from network + while ((network_parameter.connection_status != NSAPI_STATUS_DISCONNECTED) && delay_timeout < NW_DISCONNECT_TIMEOUT) { + ret_val = scl_get_nw_parameters(&network_parameter); + wait_us(NW_DELAY_TIME_US); + delay_timeout++; + } + + if (delay_timeout >= NW_DISCONNECT_TIMEOUT) { + return NSAPI_ERROR_TIMEOUT; + } + + // bring down + int err = _interface->bringdown(); + if (err) { + return err; + } + + scl_emac_wifi_link_state_changed(false); + + return NSAPI_ERROR_OK; +} + +int SclSTAInterface::scan(WiFiAccessPoint *res, unsigned count) +{ + /* To Do */ + return NSAPI_ERROR_UNSUPPORTED; +} + +int8_t SclSTAInterface::get_rssi() +{ + int32_t rssi; + scl_result_t res; + + if (!_scl_emac.powered_up) { + _scl_emac.power_up(); + } + + res = (scl_result_t) scl_wifi_get_rssi(&rssi); + if (res == SCL_ERROR) { + return SCL_ERROR; + } + + return (int8_t)rssi; +} + +int SclSTAInterface::is_interface_connected(void) +{ + if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) { + return SCL_SUCCESS; + } else { + return SCL_CONNECTION_LOST; + } +} + +int SclSTAInterface::get_bssid(uint8_t *bssid) +{ + scl_mac_t ap_mac; + scl_result_t res = SCL_SUCCESS; + + if (bssid == NULL) { + return SCL_BADARG; + } + + memset(&ap_mac, 0, sizeof(ap_mac)); + if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) { + res = (scl_result_t) scl_wifi_get_bssid(&ap_mac); + if (res == SCL_SUCCESS) { + memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet)); + } + } else { + return SCL_CONNECTION_LOST; + } + return res; +} + +int SclSTAInterface::wifi_set_up(void) +{ + int res = SCL_SUCCESS; + res = scl_wifi_set_up(); + return res; +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h new file mode 100644 index 0000000..801a9a5 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h @@ -0,0 +1,165 @@ +/* + * Copyright 2018-2020 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SCL_STA_INTERFACE_H +#define SCL_STA_INTERFACE_H + + +/** @file + * Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects + */ + +#include "netsocket/WiFiInterface.h" +#include "netsocket/EMACInterface.h" +#include "netsocket/OnboardNetworkStack.h" +#include "scl_emac.h" +#include "scl_wifi_api.h" +#include "scl_types.h" +#define MAX_SSID_LENGTH (33) /**< Maximum ssid length */ +#define MAX_PASSWORD_LENGTH (64) /**< Maximum password length */ + +/** SclSTAInterface class + * Implementation of the Network Stack for the SCL + */ +class SclSTAInterface : public WiFiInterface, public EMACInterface { +public: + + SclSTAInterface( + SCL_EMAC &emac = SCL_EMAC::get_instance(), + OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); + + /** Gets the current instance of the SclSTAInterface + * + * @return Pointer to the object of class SclSTAInterface. + */ + static SclSTAInterface *get_default_instance(); + + /** Turns on the Wi-Fi device + * + * @return void + */ + void wifi_on(); + + /** Starts the interface + * + * Attempts to connect to a Wi-Fi network. Requires ssid and passphrase to be set. + * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned. + * + * @return 0 on success, negative error code on failure. + */ + nsapi_error_t connect(); + + /** Starts the interface + * + * Attempts to connect to a Wi-Fi network. + * + * @param ssid Name of the network to connect to. + * @param pass Security passphrase to connect to the network. + * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE). + * @param channel This parameter is not supported, setting it to a value other than 0 will result in NSAPI_ERROR_UNSUPPORTED. + * @return 0 on success, negative error code on failure. + */ + nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0); + + /** Disconnects the interface + * + * @return 0 on success, negative error code on failure. + */ + nsapi_error_t disconnect(); + + /** Set the Wi-Fi network credentials + * + * @param ssid Name of the network to connect to. + * @param pass Security passphrase to connect to the network. + * @param security Type of encryption for connection. + * (defaults to NSAPI_SECURITY_NONE) + * @return 0 on success, negative error code on failure. + */ + nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE); + + /** Sets the Wi-Fi network channel - NOT SUPPORTED + * + * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED. + * + * @param channel Channel on which the connection is to be made (Default: 0). + * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED. + */ + nsapi_error_t set_channel(uint8_t channel) + { + if (channel != 0) { + return NSAPI_ERROR_UNSUPPORTED; + } + return 0; + } + + /** Set blocking status of interface. + * Nonblocking mode is not supported. + * + * @param blocking True if connect is blocking + * @return 0 on success, negative error code on failure + */ + nsapi_error_t set_blocking(bool blocking) + { + if (blocking) { + _blocking = blocking; + return NSAPI_ERROR_OK; + } else { + return NSAPI_ERROR_UNSUPPORTED; + } + } + /** Gets the current radio signal strength for active connection + * + * @return Connection strength in dBm (negative value). + */ + int8_t get_rssi(); + + /** Scans for available networks - NOT SUPPORTED + * + * @return NSAPI_ERROR_UNSUPPORTED + */ + int scan(WiFiAccessPoint *res, unsigned count); + + /** This function is used to indicate if the device is connected to the network. + * + * @return SCL_SUCCESS if device is connected. + */ + int is_interface_connected(); + + /** Gets the BSSID (MAC address of device connected to). + * + * @param bssid Pointer to the BSSID value. + * @return SCL_SUCCESS if BSSID is obtained successfully. + * @return SCL_BADARG if input parameter is NULL. + * @return SCL_ERROR if unable to fetch BSSID. + */ + int get_bssid(uint8_t *bssid); + + /** This function is used to set up the Wi-Fi interface. + * This function should be used after the wifi_on. + * + * @return SCL_SUCCESS if the Wi-Fi interface is set up successfully. + */ + int wifi_set_up(void); + +private: + + char _ssid[MAX_SSID_LENGTH]; /**< The longest possible name (defined in 802.11) +1 for the \0 */ + char _pass[MAX_PASSWORD_LENGTH]; /**< The longest allowed passphrase + 1 */ + nsapi_security_t _security; /**< Security type */ + SCL_EMAC &_scl_emac; /**< SCL_EMAC object */ +}; +#endif /* ifndef SCL_STA_INTERFACE_H */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp new file mode 100644 index 0000000..59cb5ef --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2018-2020 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SclSTAInterface.h" + +/** @file +* Provides function definition to override get_target_default_intance of WiFiInterface and NetworkInterface classes +*/ + +/** + * Returns the WiFiInterface Object + * This function can be called using WiFiInterface or NetworkInterface objects + * + * @return pointer to WiFiInterface object. + */ + +WiFiInterface *WiFiInterface::get_target_default_instance() +{ + static SclSTAInterface wifi; + return &wifi; +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp new file mode 100644 index 0000000..24c3408 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp @@ -0,0 +1,206 @@ +/* + * Copyright 2018-2020 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" +#include "scl_emac.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "mbed_shared_queues.h" +#include "scl_buffer_api.h" +#include "cy_result.h" +#include "cy_pdl.h" +#include "scl_ipc.h" + +/** @file + * Provides EMAC interface functions to be used with the SCL_EMAC object + */ + +SCL_EMAC::SCL_EMAC(scl_interface_role_t role) + : interface_type(role) +{ +} + +SCL_EMAC::SCL_EMAC() + : interface_type(SCL_STA_ROLE) +{ +} + +SCL_EMAC &SCL_EMAC::get_instance() +{ + return get_instance(SCL_STA_ROLE); +} + +SCL_EMAC &SCL_EMAC::get_instance(scl_interface_role_t role) +{ + static SCL_EMAC emac_sta(SCL_STA_ROLE); + static SCL_EMAC emac_ap(SCL_AP_ROLE); + return role == SCL_AP_ROLE ? emac_ap : emac_sta; +} + +uint32_t SCL_EMAC::get_mtu_size() const +{ + return SCL_PAYLOAD_MTU; +} + +uint32_t SCL_EMAC::get_align_preference() const +{ + return 0; +} + +void SCL_EMAC::add_multicast_group(const uint8_t *addr) +{ + memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet)); + scl_wifi_register_multicast_address(&multicast_addr); +} + +void SCL_EMAC::remove_multicast_group(const uint8_t *address) +{ + /* To Do */ +} +void SCL_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void SCL_EMAC::power_down() +{ + /* No-op at this stage */ +} + +bool SCL_EMAC::power_up() +{ + if (!powered_up) { +#ifdef MBED_TEST_MODE + scl_init(); +#endif + if (!scl_wifi_on()) { + SCL_LOG(("WiFi failed to turn on\r\n")); + return false; + } + powered_up = true; + if (link_state && emac_link_state_cb) { + emac_link_state_cb(link_state); + } + } + return true; +} + +bool SCL_EMAC::get_hwaddr(uint8_t *addr) const +{ + scl_mac_t mac; + scl_result_t res = scl_wifi_get_mac_address(&mac); + if (res == SCL_SUCCESS) { + memcpy(addr, mac.octet, sizeof(mac.octet)); + return true; + } else { + SCL_LOG(("Unable to get MAC address\r\n")); + return false; + } +} + +void SCL_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +uint8_t SCL_EMAC::get_hwaddr_size() const +{ + scl_mac_t mac; + return sizeof(mac.octet); +} + +void SCL_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void SCL_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void SCL_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +bool SCL_EMAC::link_out(emac_mem_buf_t *buf) +{ + scl_result_t retval; + scl_tx_buf_t scl_tx_data; + scl_tx_data.size = memory_manager->get_total_len(buf); + scl_tx_data.buffer = buf; + if (buf == NULL) { + return false; + } + + retval = scl_network_send_ethernet_data(scl_tx_data); //Buffer is copied on Network Processor + if (retval != SCL_SUCCESS) { + return false; + } + memory_manager->free(buf); + return true; +} + +void SCL_EMAC::get_ifname(char *name, uint8_t size) const +{ + if (name != NULL) { + memcpy(name, "scl", size); + } +} + +void SCL_EMAC::set_activity_cb(mbed::Callback cb) +{ + activity_cb = cb; +} + +extern "C" +{ + void scl_network_process_ethernet_data(scl_buffer_t buffer) + { + emac_mem_buf_t *mem_buf = NULL; + + SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE); + + if (!emac.powered_up && !emac.emac_link_input_cb) { + scl_buffer_release(buffer, SCL_NETWORK_RX); + return; + } + mem_buf = buffer; + if (emac.activity_cb) { + emac.activity_cb(false); + } + emac.emac_link_input_cb(mem_buf); + } + + void scl_emac_wifi_link_state_changed(bool state_up) + { + SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE); + + emac.link_state = state_up; + if (emac.emac_link_state_cb) { + emac.emac_link_state_cb(state_up); + } + } +} // extern "C" + + diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h new file mode 100644 index 0000000..e6e3ecd --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h @@ -0,0 +1,189 @@ +/* + * Copyright 2018-2020 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SCL_EMAC_H_ +#define SCL_EMAC_H_ + +/** @file + * Provides EMAC interface functions to be used with the SCL_EMAC object + * + */ +#include "EMAC.h" +#include "EMACInterface.h" +#include "WiFiInterface.h" +#include "scl_common.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" +#include "scl_wifi_api.h" +class SCL_EMAC : public EMAC { +public: + SCL_EMAC(); + SCL_EMAC(scl_interface_role_t itype); + + /** + * Get the EMAC instance + * + * @return Reference to SCL_EMAC object. + */ + static SCL_EMAC &get_instance(); + + /** + * Get the EMAC instance + * + * @param role Interface type. + * + * @return Reference to SCL_EMAC object. + */ + static SCL_EMAC &get_instance(scl_interface_role_t role); + + /** + * Returns the maximum transmission unit + * + * @return MTU in bytes. + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets the memory buffer alignment preference + * + * Gets the preferred memory buffer alignment of the EMAC device. IP stack may or may not + * align with the link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes. + */ + virtual uint32_t get_align_preference() const; + + /** + * Returns the interface name + * + * @param name Pointer to the location where the name should be written. + * @param size Maximum number of characters to copy. + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns the size of the underlying interface HW address size. + * + * @return HW address size in bytes. + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Returns the interface supplied HW address + * Copies the HW address to the provided memory + * @param addr HW address of the underlying interface. It must be of correct size. See @a get_hwaddr_size. + * @return True if HW address is available. + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for the interface + * + * Provided address must be of correct size. See @a get_hwaddr_size. + * + * Called to set the MAC address to be used - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * This cannot be called from an interrupt context. + * + * @param buf Packet to be sent. + * @return True if the packet was sent successfully. False otherwise. + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success. False in case of an error. + */ + virtual bool power_up(); + + /** + * De-initializes the HW + */ + virtual void power_down(); + + /** + * Sets a callback that is called for packets received for a given interface + * + * @param input_cb Function to be registered as a callback. + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that is called on changes in the link status for a given interface + * + * @param state_cb Function to be registered as a callback. + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Adds a device to a multicast group + * + * @param address A multicast group hardware address. + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Removes a device from a multicast group + * + * @param address A multicast group hardware address. + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Requests reception of all multicast packets + * + * @param all True to receive all multicasts. + * False to receive only multicasts addressed to specified groups. + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager. + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + /** Sets callback to receive EMAC activity events + * + * @param activity_cb The callback for activity events. + */ + virtual void set_activity_cb(mbed::Callback activity_cb); + + emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb = NULL; /**< Callback for network connection status */ + EMACMemoryManager *memory_manager; /**< Pointer to hold memory manager object */ + bool powered_up = false; /**< Flag for Wi-Fi power on status */ + bool link_state = false; /**< Flag for network connection status */ + scl_interface_role_t interface_type; /**< Type of the interface */ + scl_mac_t multicast_addr; /**< Multicast address */ + mbed::Callback activity_cb; /**< Callback for activity on network */ + +}; +/** Sends the change in network connection state to network stack +* +* @param state_up Connection status. +*/ +extern "C" void scl_emac_wifi_link_state_changed(bool state_up); + +#endif /* SCL_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp new file mode 100644 index 0000000..ca84423 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CyDhcpServer.h" +#include "cy_utils.h" +#include "Callback.h" +#include "def.h" +#include "whd_types.h" + +#ifdef DHCP_EXTENSIVE_DEBUG +extern "C" void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title); +#endif + +/* UDP port numbers for DHCP server and client */ +#define IP_PORT_DHCP_SERVER (67) +#define IP_PORT_DHCP_CLIENT (68) + +/* BOOTP operations */ +#define BOOTP_OP_REQUEST (1) +#define BOOTP_OP_REPLY (2) + +/* DCHP message types */ +#define DHCP_MSG_TYPE_DISCOVER (1) +#define DHCP_MSG_TYPE_OFFER (2) +#define DHCP_MSG_TYPE_REQUEST (3) +#define DHCP_MSG_TYPE_DECLINE (4) +#define DHCP_MSG_TYPE_ACK (5) +#define DHCP_MSG_TYPE_NACK (6) +#define DHCP_MSG_TYPE_RELEASE (7) +#define DHCP_MSG_TYPE_INFORM (8) +#define DHCP_MSG_TYPE_INVALID (255) + +#define DHCP_MSG_MAGIC_COOKIE (0x63825363) + +#define DHCP_STACK_SIZE (8*1024) + +/********************* Options manipulation functions ***********************************/ +static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype) +{ + if (index + sizeof(dhcp_packet_t) - 1 + 1 >= DHCP_PACKET_SIZE) { + printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); + return; + } + + dhcp->Options[index++] = optype; + + return; +} + +static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t value) +{ + if (index + sizeof(dhcp_packet_t) - 1 + 3 >= DHCP_PACKET_SIZE) { + printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); + return; + } + + dhcp->Options[index++] = optype; + dhcp->Options[index++] = 0x01; + dhcp->Options[index++] = value; + + return; +} + +static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint16_t value) +{ + if (index + sizeof(dhcp_packet_t) - 1 + 4 >= DHCP_PACKET_SIZE) { + printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); + return; + } + + dhcp->Options[index++] = optype; + dhcp->Options[index++] = 0x02; + dhcp->Options[index++] = static_cast((value >> 0) & 0xFF); + dhcp->Options[index++] = static_cast((value >> 8) & 0xFF); + + return; +} + +static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint32_t value) +{ + if (index + sizeof(dhcp_packet_t) - 1 + 6 >= DHCP_PACKET_SIZE) { + printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); + return; + } + + dhcp->Options[index++] = optype; + dhcp->Options[index++] = 0x04; + dhcp->Options[index++] = static_cast((value >> 0) & 0xFF); + dhcp->Options[index++] = static_cast((value >> 8) & 0xFF); + dhcp->Options[index++] = static_cast((value >> 16) & 0xFF); + dhcp->Options[index++] = static_cast((value >> 24) & 0xFF); + + return; +} + +static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t *value, uint32_t size) +{ + if (index + sizeof(dhcp_packet_t) - 1 + 2 + size >= DHCP_PACKET_SIZE) { + printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); + return; + } + + dhcp->Options[index++] = optype; + dhcp->Options[index++] = size; + memcpy(&dhcp->Options[index], value, size); + index += size; + + return; +} + +static const uint8_t *findOption(const dhcp_packet_t *request, uint8_t option_num) +{ + const uint8_t *option_ptr = request->Options; + while ((option_ptr[0] != DHCP_END_OPTION_CODE) && + (option_ptr[0] != option_num) && + (option_ptr < ((const uint8_t *)request) + DHCP_PACKET_SIZE)) { + option_ptr += option_ptr[1] + 2; + } + + /* Was the option found? */ + if (option_ptr[0] == option_num) { + return &option_ptr[2]; + } + return NULL; +} + +static void addCommonOptions(dhcp_packet_t *dhcp, uint32_t &index, const uint32_t server_addr, const uint32_t netmask) +{ + /* Prepare the Web proxy auto discovery URL */ + char wpad_sample_url[] = "http://xxx.xxx.xxx.xxx/wpad.dat"; + char ip_str[16]; + ipv4_to_string(ip_str, htonl(server_addr)); + memcpy(&wpad_sample_url[7], &ip_str[0], 15); + + /* Server identifier */ + addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, server_addr); + /* Lease Time */ + addOption(dhcp, index, DHCP_LEASETIME_OPTION_CODE, static_cast(0x00015180)); + /* Subnet Mask */ + addOption(dhcp, index, DHCP_SUBNETMASK_OPTION_CODE, htonl(netmask)); + /* Web proxy auto discovery URL */ + addOption(dhcp, index, DHCP_WPAD_OPTION_CODE, (uint8_t *)&wpad_sample_url[0], strlen(wpad_sample_url)); + /* Router (gateway) */ + addOption(dhcp, index, DHCP_ROUTER_OPTION_CODE, htonl(server_addr)); + /* DNS server */ + addOption(dhcp, index, DHCP_DNS_SERVER_OPTION_CODE, htonl(server_addr)); + /* Interface MTU */ + addOption(dhcp, index, DHCP_MTU_OPTION_CODE, static_cast(WHD_PAYLOAD_MTU)); +} + +static void sendPacket(UDPSocket *socket, dhcp_packet_t *dhcp, uint32_t size) +{ + nsapi_size_or_error_t err; + uint32_t broadcast_ip = 0xFFFFFFFF; + char string_addr[16]; + ipv4_to_string(string_addr, htonl(broadcast_ip)); + SocketAddress sock_addr(string_addr, IP_PORT_DHCP_CLIENT); + + err = socket->sendto(sock_addr, reinterpret_cast(dhcp), size); + if (err < 0) { + printf("DHCP ERROR: Packet send failure with error %d.", err); + } else if (err != (int)size) { + printf("DHCP ERROR: Could not send entire packet. Only %d bytes were sent.", err); + } +} + +/********************* Cache utility functions ***********************************/ +void CyDhcpServer::setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr) +{ + uint32_t a; + uint32_t first_empty_slot; + uint32_t cached_slot; + char empty_cache[NSAPI_IPv6_SIZE] = ""; + + /* Search for empty slot in cache */ + for (a = 0, first_empty_slot = DHCP_IP_ADDRESS_CACHE_MAX, cached_slot = DHCP_IP_ADDRESS_CACHE_MAX; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { + /* Check for matching MAC address */ + if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { + /* Cached device found */ + cached_slot = a; + break; + } else if (first_empty_slot == DHCP_IP_ADDRESS_CACHE_MAX && memcmp(&_mac_addr_cache[a], &empty_cache, sizeof(cy_mac_addr_t)) == 0) { + /* Device not found in cache. Return the first empty slot */ + first_empty_slot = a; + } + } + + if (cached_slot != DHCP_IP_ADDRESS_CACHE_MAX) { + /* Update IP address of cached device */ + _ip_addr_cache[cached_slot] = addr; + } else if (first_empty_slot != DHCP_IP_ADDRESS_CACHE_MAX) { + /* Add device to the first empty slot */ + _mac_addr_cache[first_empty_slot] = mac_id; + _ip_addr_cache[first_empty_slot] = addr; + } else { + /* Cache is full. Add device to slot 0 */ + _mac_addr_cache[0] = mac_id; + _ip_addr_cache [0] = addr; + } +} + +bool CyDhcpServer::lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr) +{ + /* Check whether device is already cached */ + for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { + if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { + addr = _ip_addr_cache[a]; + return true; + } + } + return false; +} + +void CyDhcpServer::freeAddress(const cy_mac_addr_t &mac_id) +{ + /* Check whether device is already cached */ + for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { + if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { + memset(&_mac_addr_cache[a], 0, sizeof(_mac_addr_cache[a])); + memset(&_ip_addr_cache[a], 0, sizeof(_ip_addr_cache[a])); + } + } +} + +void CyDhcpServer::handleDiscover(dhcp_packet_t *dhcp) +{ +#ifdef DHCP_EXTENSIVE_DEBUG + dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP DISCOVER RECEIVED"); +#endif + + uint32_t index; + cy_mac_addr_t client_mac; + cy_ip_addr_t client_ip; + + memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac)); + if (!lookupAddress(client_mac, client_ip)) { + client_ip = _available_addr; + } + + memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy)); + memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3); + + dhcp->Opcode = BOOTP_OP_REPLY; + dhcp->YourIpAddr = htonl(client_ip.addrv4.addr); + dhcp->MagicCookie = htonl(static_cast(DHCP_MSG_MAGIC_COOKIE)); + + /* Add options */ + index = 0; + addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_OFFER)); + addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr); + addOption(dhcp, index, static_cast(DHCP_END_OPTION_CODE)); + + uint32_t size = sizeof(dhcp_packet_t) + index - 1; + CY_ASSERT(size <= DHCP_PACKET_SIZE); + +#ifdef DHCP_EXTENSIVE_DEBUG + dhcp_server_print_header_info(dhcp, size, "\n\nDHCP OFFER SENT"); +#endif + sendPacket(&_socket, dhcp, size); +} + +void CyDhcpServer::handleRequest(dhcp_packet_t *dhcp) +{ +#ifdef DHCP_EXTENSIVE_DEBUG + dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST RECEIVED"); +#endif + + cy_mac_addr_t client_mac; + cy_ip_addr_t client_ip; + cy_ip_addr_t req_ip; + bool increment = false; + uint32_t index; + + /* Check that the REQUEST is for this server */ + uint32_t *server_id_req = (uint32_t *)findOption(dhcp, DHCP_SERVER_IDENTIFIER_OPTION_CODE); + if ((server_id_req == NULL) || ((server_id_req != NULL) && (_server_addr.addrv4.addr != *server_id_req))) { + return; /* Server ID was not found or does not match local IP address */ + } + + /* Locate the requested address in the options and keep requested address */ + req_ip.addrv4.addr = ntohl(*(uint32_t *)findOption(dhcp, DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE)); + + memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac)); + if (!lookupAddress(client_mac, client_ip)) { + client_ip = _available_addr; + increment = true; + } + + memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy)); + memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3); + + dhcp->Opcode = BOOTP_OP_REPLY; + dhcp->MagicCookie = htonl(static_cast(DHCP_MSG_MAGIC_COOKIE)); + + index = 0; + /* Check if the requested IP address matches one we have assigned */ + if (req_ip.addrv4.addr != client_ip.addrv4.addr) { + /* Request is not for the assigned IP - force client to take next available IP by sending NAK */ + addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_NACK)); + addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, _server_addr.addrv4.addr); + printf("\n\nDHCP_THREAD: %d REQUEST NAK\n", __LINE__); + } else { + dhcp->YourIpAddr = htonl(client_ip.addrv4.addr); + + addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_ACK)); + addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr); + + if (increment) { + uint32_t ip_mask = ~(_netmask.addrv4.addr); + uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr; + do { + _available_addr.addrv4.addr = subnet | ((_available_addr.addrv4.addr + 1) & ip_mask); + } while (_available_addr.addrv4.addr == _server_addr.addrv4.addr); + } + setAddress(client_mac, client_ip); + } + addOption(dhcp, index, static_cast(DHCP_END_OPTION_CODE)); + + uint32_t size = sizeof(dhcp_packet_t) + index - 1; + CY_ASSERT(size <= DHCP_PACKET_SIZE); + +#ifdef DHCP_EXTENSIVE_DEBUG + dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST REPLY SENT"); +#endif + sendPacket(&_socket, dhcp, size); +} + +void CyDhcpServer::runServer(void) +{ + nsapi_size_or_error_t err_or_size; + + _running = true; + + /* Create receive DHCP socket */ + _socket.open(_nstack); + char iface_name[8] = {0}; + _niface->get_interface_name(iface_name); + _socket.setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, iface_name, strlen(iface_name)); + _socket.bind((uint16_t)IP_PORT_DHCP_SERVER); + + /* Save the current netmask to be sent in DHCP packets as the 'subnet mask option' */ + SocketAddress sock_addr; + _niface->get_ip_address(&sock_addr); + _server_addr.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address()); + _niface->get_netmask(&sock_addr); + _netmask.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address()); + +#ifdef DHCP_EXTENSIVE_DEBUG + printf("DHCP Server started.\n"); + printf("DHCP Server: IP : %s\n", _niface->get_ip_address()); + printf("DHCP Server: Netmask: %s\n", _niface->get_netmask()); + printf("DHCP Server: Gateway: %s\n", _niface->get_gateway()); + printf("DHCP Server: MAC : %s\n\n", _niface->get_mac_address()); +#endif + + /* Calculate the first available IP address which will be served - based on the netmask and the local IP */ + uint32_t ip_mask = ~(_netmask.addrv4.addr); + uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr; + _available_addr.addrv4.addr = subnet | ((_server_addr.addrv4.addr + 1) & ip_mask); + + while (_running) { + /* Sleep until data is received from socket. */ + err_or_size = _socket.recv(_buff, DHCP_PACKET_SIZE); + /* Options field in DHCP header is variable length. We are looking for option "DHCP Message Type" that is 3 octets in size (code, length and type) */ + /* If the return value is <0, it is an error; if it is >=0, it is the received length */ + if (err_or_size < 0 || err_or_size < (int32_t)sizeof(dhcp_packet_t)) { + continue; + } + + dhcp_packet_t *dhcp = reinterpret_cast(_buff); + /* Check if the option in the dhcp header is "DHCP Message Type", code value for option "DHCP Message Type" is 53 as per rfc2132 */ + if (dhcp->Options[0] != DHCP_MESSAGETYPE_OPTION_CODE) { + printf("%d: %s received option code wrong: %d != %d\n", __LINE__, __func__, dhcp->Options[0], DHCP_MESSAGETYPE_OPTION_CODE); + continue; + } + + uint8_t msg_type = dhcp->Options[2]; + switch (msg_type) { + case DHCP_MSG_TYPE_DISCOVER: + handleDiscover(dhcp); + break; + case DHCP_MSG_TYPE_REQUEST: + handleRequest(dhcp); + break; + default: + printf("DHCP ERROR: Unhandled dhcp packet type, %d", msg_type); + break; + } + } +} + +void CyDhcpServer::threadWrapper(CyDhcpServer *obj) +{ + obj->runServer(); +} + +CyDhcpServer::CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface) + : _nstack(nstack), + _niface(niface), + _thread(osPriorityNormal, DHCP_STACK_SIZE, NULL, "DHCPserver") {} + +CyDhcpServer::~CyDhcpServer() +{ + stop(); +} + +cy_rslt_t CyDhcpServer::start(void) +{ + cy_rslt_t result = CY_RSLT_SUCCESS; + if (!_running) { + CY_ASSERT(_nstack != NULL); + + /* Clear cache */ + memset(_mac_addr_cache, 0, sizeof(_mac_addr_cache)); + memset(_ip_addr_cache, 0, sizeof(_ip_addr_cache)); + + /* Start DHCP server */ + if (osOK != _thread.start(mbed::callback(threadWrapper, this))) { + result = CY_DHCP_THREAD_CREATION_FAILED; + } + } + return result; +} + +cy_rslt_t CyDhcpServer::stop(void) +{ + cy_rslt_t result = CY_RSLT_SUCCESS; + if (_running) { + _running = false; + if (NSAPI_ERROR_OK != _socket.close()) { + printf("DHCP ERROR: DHCP socket closure failed.\n"); + result = CY_DHCP_STOP_FAILED; + } + if (osOK != _thread.join()) { + printf("DHCP ERROR: DHCP thread join failed.\n"); + result = CY_DHCP_STOP_FAILED; + } + } + return result; +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h new file mode 100644 index 0000000..b11d031 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WHD_DHCP_SERVER_H +#define WHD_DHCP_SERVER_H + +#include "cy_result.h" +#include "cy_syslib.h" +#include "cynetwork_utils.h" +#include "UDPSocket.h" +#include "netsocket/NetworkInterface.h" +#include "netsocket/NetworkStack.h" +#include "rtos.h" + +/* DHCP data structure */ +typedef struct { + uint8_t Opcode; /* packet opcode type */ + uint8_t HwType; /* hardware addr type */ + uint8_t HwLen; /* hardware addr length */ + uint8_t Hops; /* gateway hops */ + uint32_t TransactionId; /* transaction ID */ + uint16_t SecsElapsed; /* seconds since boot began */ + uint16_t Flags; + uint32_t ClientIpAddr; /* client IP address */ + uint32_t YourIpAddr; /* 'your' IP address */ + uint32_t ServerIpAddr; /* server IP address */ + uint32_t GatewayIpAddr; /* gateway IP address */ + uint8_t ClientHwAddr[16]; /* client hardware address */ + uint8_t Legacy[192]; /* SName, File */ + uint32_t MagicCookie; + uint8_t Options[3]; /* options area */ + /* as of RFC2131 it is variable length */ +} dhcp_packet_t; + +#define DHCP_SUBNETMASK_OPTION_CODE (1) +#define DHCP_ROUTER_OPTION_CODE (3) +#define DHCP_DNS_SERVER_OPTION_CODE (6) +#define DHCP_HOST_NAME_OPTION_CODE (12) +#define DHCP_MTU_OPTION_CODE (26) +#define DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE (50) +#define DHCP_LEASETIME_OPTION_CODE (51) +#define DHCP_MESSAGETYPE_OPTION_CODE (53) +#define DHCP_SERVER_IDENTIFIER_OPTION_CODE (54) +#define DHCP_PARAM_REQUEST_LIST_OPTION_CODE (55) +#define DHCP_WPAD_OPTION_CODE (252) +#define DHCP_END_OPTION_CODE (255) + +#define DHCP_IP_ADDRESS_CACHE_MAX (5) +#define ADDITIONAL_OPTION_BYTES (272) +#define DHCP_PACKET_SIZE (sizeof(dhcp_packet_t) + ADDITIONAL_OPTION_BYTES) + +/** DHCP thread could not be started */ +#define CY_DHCP_THREAD_CREATION_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 0) + +/** Error while trying to stop the DHCP server */ +#define CY_DHCP_STOP_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 1) + +/** + * Implementation of a DHCP sever + */ +class CyDhcpServer { +public: + /** + * Create a DHCP server. + */ + CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface); + + /** + * Delete the DHCP server. + */ + virtual ~CyDhcpServer(); + + /** + * Start a DHCP server instance. + * @return CY_RSLT_SUCCESS on success otherwise error. + */ + cy_rslt_t start(void); + + /** + * Stop a DHCP server instance. + * @return CY_RSLT_SUCCESS on success otherwise error. + */ + cy_rslt_t stop(void); + +private: + NetworkStack *_nstack = NULL; + NetworkInterface *_niface = NULL; + UDPSocket _socket; + Thread _thread; + bool _running = false; + + cy_ip_addr_t _available_addr; + cy_ip_addr_t _server_addr; + cy_ip_addr_t _netmask; + + cy_mac_addr_t _mac_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX]; + cy_ip_addr_t _ip_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX]; + uint8_t _buff[DHCP_PACKET_SIZE]; + + static void threadWrapper(CyDhcpServer *obj); + void runServer(void); + + void setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr); + bool lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr); + void freeAddress(const cy_mac_addr_t &mac_id); + + void handleDiscover(dhcp_packet_t *dhcp); + void handleRequest(dhcp_packet_t *dhcp); +}; + +#endif /* WHD_DHCP_SERVER_H */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp new file mode 100644 index 0000000..9c8b1d4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp @@ -0,0 +1,65 @@ +/* WHD Access Point Interface Implementation + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "WhdAccessPoint.h" + +WhdAccessPoint::WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len) : + WiFiAccessPoint(ap), _bss_type(bss_type) +{ + _ie_ptr = (uint8_t *)malloc(ie_len * sizeof(uint8_t)); + if (_ie_ptr != NULL) { + _ie_len = ie_len; + memcpy(_ie_ptr, ie_ptr, ie_len * sizeof(uint8_t)); + } +} + +WhdAccessPoint &WhdAccessPoint::operator=(WhdAccessPoint &&rhs) +{ + if (this != &rhs) { + WiFiAccessPoint::operator=(rhs); + _bss_type = rhs._bss_type; + _ie_ptr = rhs._ie_ptr; + _ie_len = rhs._ie_len; + rhs._ie_ptr = NULL; + rhs._ie_len = 0; + } + return *this; +} + +whd_bss_type_t WhdAccessPoint::get_bss_type() const +{ + return _bss_type; +} + +uint8_t *WhdAccessPoint::get_ie_data() const +{ + return _ie_ptr; +} + +uint32_t WhdAccessPoint::get_ie_len() const +{ + return _ie_len; +} + +WhdAccessPoint::~WhdAccessPoint() +{ + if (_ie_ptr != NULL) { + free(_ie_ptr); + } +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h new file mode 100644 index 0000000..5ceaba6 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h @@ -0,0 +1,74 @@ +/* WHD Access Point Interface + * Copyright (c) 2017-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WHD_ACCESS_POINT_H +#define WHD_ACCESS_POINT_H + +#include "netsocket/WiFiAccessPoint.h" +#include "whd_types.h" + +/* Enum for scan result type */ +enum scan_result_type { + SRES_TYPE_WIFI_ACCESS_POINT, + SRES_TYPE_WHD_ACCESS_POINT +}; + +/** WhdAccessPoint class + * + * Class that represents a Whd Access Point + * which contains additional Whd specific information + */ +class WhdAccessPoint : public WiFiAccessPoint { +public: + WhdAccessPoint() : WiFiAccessPoint() {}; + WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len); + + /** Define move assignment and prevent copy-assignment + * + * Due to IE element data could have large memory footprint, + * only move assignment is allowed. + */ + WhdAccessPoint &operator=(WhdAccessPoint &&rhs); + WhdAccessPoint &operator=(const WhdAccessPoint &rhs) = delete; + + /** Get WHD access point's bss type + * + * @return The whd_bss_type_t of the access point + */ + whd_bss_type_t get_bss_type() const; + + /** Get WHD access point's IE data + * + * @return The pointer to ie data buffer + */ + uint8_t *get_ie_data() const; + + /** Get WHD access point's IE length + * + * @return The ie data length + */ + uint32_t get_ie_len() const; + + virtual ~WhdAccessPoint(); + +private: + whd_bss_type_t _bss_type; + uint8_t *_ie_ptr; /**< Pointer to received Beacon/Probe Response IE(Information Element) */ + uint32_t _ie_len; /**< Length of IE(Information Element) */ +}; + +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp new file mode 100644 index 0000000..51c3675 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp @@ -0,0 +1,665 @@ +/* WHD STAION implementation of NetworkInterfaceAPI + * Copyright (c) 2017-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "WhdSTAInterface.h" +#include "nsapi.h" +#include "lwipopts.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "rtos.h" +#include "whd_emac.h" +#include "whd_wifi_api.h" +#include "whd_wlioctl.h" + +#define CMP_MAC( a, b ) (((((unsigned char*)a)[0])==(((unsigned char*)b)[0]))&& \ + ((((unsigned char*)a)[1])==(((unsigned char*)b)[1]))&& \ + ((((unsigned char*)a)[2])==(((unsigned char*)b)[2]))&& \ + ((((unsigned char*)a)[3])==(((unsigned char*)b)[3]))&& \ + ((((unsigned char*)a)[4])==(((unsigned char*)b)[4]))&& \ + ((((unsigned char*)a)[5])==(((unsigned char*)b)[5]))) + +struct whd_scan_userdata { + rtos::Semaphore *sema; + scan_result_type sres_type; + WiFiAccessPoint *aps; + std::vector *result_buff; + unsigned count; + unsigned offset; + bool scan_in_progress; +}; + +static whd_scan_userdata interal_scan_data; +static whd_scan_result_t internal_scan_result; +static uint16_t sta_link_update_entry = 0xFF; +static const whd_event_num_t sta_link_change_events[] = { + WLC_E_SET_SSID, WLC_E_LINK, WLC_E_AUTH, WLC_E_ASSOC, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, WLC_E_DISASSOC, + WLC_E_REASSOC, WLC_E_PSK_SUP, WLC_E_ACTION_FRAME_COMPLETE, WLC_E_NONE +}; + + +extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); + + +int whd_toerror(whd_result_t res) +{ + switch (res) { + case WHD_SUCCESS: + return NSAPI_ERROR_OK; + case WHD_UNSUPPORTED: + case WHD_WLAN_UNSUPPORTED: + case WHD_WLAN_ACM_NOTSUPPORTED: + return NSAPI_ERROR_UNSUPPORTED; + case WHD_BADARG: + case WHD_WLAN_BADARG: + return NSAPI_ERROR_PARAMETER; + case WHD_WLAN_NOTASSOCIATED: + case WHD_INVALID_JOIN_STATUS: + return NSAPI_ERROR_NO_CONNECTION; + case WHD_BUFFER_UNAVAILABLE_PERMANENT: + case WHD_BUFFER_UNAVAILABLE_TEMPORARY: + case WHD_RX_BUFFER_ALLOC_FAIL: + case WHD_BUFFER_ALLOC_FAIL: + case WHD_WLAN_NOMEM: + case WHD_MALLOC_FAILURE: + return NSAPI_ERROR_NO_MEMORY; + case WHD_ACCESS_POINT_NOT_FOUND: + case WHD_NETWORK_NOT_FOUND: + return NSAPI_ERROR_NO_SSID; + case WHD_NOT_AUTHENTICATED: + case WHD_INVALID_KEY: + case WHD_NOT_KEYED: + return NSAPI_ERROR_AUTH_FAILURE; + case WHD_PENDING: + case WHD_JOIN_IN_PROGRESS: + return NSAPI_ERROR_IN_PROGRESS; + case WHD_CONNECTION_LOST: + return NSAPI_ERROR_CONNECTION_LOST; + case WHD_TIMEOUT: + case WHD_EAPOL_KEY_PACKET_M1_TIMEOUT: + case WHD_EAPOL_KEY_PACKET_M3_TIMEOUT: + case WHD_EAPOL_KEY_PACKET_G1_TIMEOUT: + return NSAPI_ERROR_CONNECTION_TIMEOUT; + case WHD_WLAN_BUSY: + return NSAPI_ERROR_BUSY; + case WHD_WLAN_NODEVICE: + return NSAPI_ERROR_DEVICE_ERROR; + default: + return -res; + } +} + +static nsapi_security_t whd_tosecurity(whd_security_t sec) +{ + switch (sec) { + case WHD_SECURITY_OPEN: + return NSAPI_SECURITY_NONE; + case WHD_SECURITY_WEP_PSK: + case WHD_SECURITY_WEP_SHARED: + return NSAPI_SECURITY_WEP; + case WHD_SECURITY_WPA_MIXED_PSK: + case WHD_SECURITY_WPA_TKIP_PSK: + case WHD_SECURITY_WPA_TKIP_ENT: + return NSAPI_SECURITY_WPA; + case WHD_SECURITY_WPA2_WPA_AES_PSK: + case WHD_SECURITY_WPA2_WPA_MIXED_PSK: + return NSAPI_SECURITY_WPA_WPA2; + case WHD_SECURITY_WPA2_MIXED_ENT: + return NSAPI_SECURITY_WPA2_ENT; + case WHD_SECURITY_WPA2_MIXED_PSK: + case WHD_SECURITY_WPA2_AES_PSK: + case WHD_SECURITY_WPA2_AES_ENT: + case WHD_SECURITY_WPA2_FBT_PSK: + case WHD_SECURITY_WPA2_FBT_ENT: + return NSAPI_SECURITY_WPA2; + case WHD_SECURITY_WPA3_SAE: + return NSAPI_SECURITY_WPA3; + case WHD_SECURITY_WPA3_WPA2_PSK: + return NSAPI_SECURITY_WPA3_WPA2; + default: + return NSAPI_SECURITY_UNKNOWN; + } +} + +whd_security_t whd_fromsecurity(nsapi_security_t sec) +{ + switch (sec) { + case NSAPI_SECURITY_NONE: + return WHD_SECURITY_OPEN; + case NSAPI_SECURITY_WEP: + return WHD_SECURITY_WEP_PSK; + case NSAPI_SECURITY_WPA: + return WHD_SECURITY_WPA_MIXED_PSK; + case NSAPI_SECURITY_WPA2: + return WHD_SECURITY_WPA2_AES_PSK; + case NSAPI_SECURITY_WPA_WPA2: + return WHD_SECURITY_WPA2_MIXED_PSK; + case NSAPI_SECURITY_WPA2_ENT: + return WHD_SECURITY_WPA2_MIXED_ENT; + case NSAPI_SECURITY_WPA3: + return WHD_SECURITY_WPA3_SAE; + case NSAPI_SECURITY_WPA3_WPA2: + return WHD_SECURITY_WPA3_WPA2_PSK; + default: + return WHD_SECURITY_UNKNOWN; + } +} + +static void *whd_wifi_link_state_change_handler(whd_interface_t ifp, + const whd_event_header_t *event_header, + const uint8_t *event_data, + void *handler_user_data) +{ + UNUSED_PARAMETER(event_data); + + if (event_header->bsscfgidx >= WHD_INTERFACE_MAX) { + WPRINT_WHD_DEBUG(("%s: event_header: Bad interface\n", __FUNCTION__)); + return NULL; + } + + if ((event_header->event_type == WLC_E_DEAUTH_IND) || + (event_header->event_type == WLC_E_DISASSOC_IND) || + ((event_header->event_type == WLC_E_PSK_SUP) && + (event_header->status == WLC_SUP_KEYED) && + (event_header->reason == WLC_E_SUP_DEAUTH))) { + whd_emac_wifi_link_state_changed(ifp, WHD_FALSE); + return handler_user_data; + } + + if (((event_header->event_type == WLC_E_PSK_SUP) && + (event_header->status == WLC_SUP_KEYED) && + (event_header->reason == WLC_E_SUP_OTHER)) || + (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)) { + whd_emac_wifi_link_state_changed(ifp, WHD_TRUE); + return handler_user_data; + } + + return handler_user_data; +} + + +MBED_WEAK WhdSTAInterface::OlmInterface &WhdSTAInterface::OlmInterface::get_default_instance() +{ + static OlmInterface olm; + return olm; +} + +WhdSTAInterface::WhdSTAInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, OlmInterface &olm, whd_interface_shared_info_t &shared) + : EMACInterface(emac, stack), + _ssid("\0"), + _pass("\0"), + _security(NSAPI_SECURITY_NONE), + _whd_emac(emac), + _olm(&olm), + _iface_shared(shared) +{ +} + +nsapi_error_t WhdSTAInterface::connect( + const char *ssid, const char *pass, + nsapi_security_t security, + uint8_t channel) +{ + int err = set_channel(channel); + if (err) { + return err; + } + + err = set_credentials(ssid, pass, security); + if (err) { + return err; + } + + return connect(); +} + +nsapi_error_t WhdSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) +{ + if ((ssid == NULL) || + (strlen(ssid) == 0) || + (pass == NULL && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) || + (strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) || + (strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA || + security == NSAPI_SECURITY_WPA_WPA2 || security == NSAPI_SECURITY_WPA3 || security == NSAPI_SECURITY_WPA3_WPA2)) + ) { + return NSAPI_ERROR_PARAMETER; + } + + memset(_ssid, 0, sizeof(_ssid)); + strncpy(_ssid, ssid, sizeof(_ssid)); + + memset(_pass, 0, sizeof(_pass)); + strncpy(_pass, pass, sizeof(_pass)); + + _security = security; + + return NSAPI_ERROR_OK; +} + +nsapi_error_t WhdSTAInterface::connect() +{ + ScopedMutexLock lock(_iface_shared.mutex); + +#define MAX_RETRY_COUNT ( 5 ) + int i; + whd_result_t res; + + // initialize wiced, this is noop if already init + if (!_whd_emac.powered_up) { + if(!_whd_emac.power_up()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + } + + res = whd_management_set_event_handler(_whd_emac.ifp, sta_link_change_events, + whd_wifi_link_state_change_handler, NULL, &sta_link_update_entry); + if (res != WHD_SUCCESS) { + return whd_toerror(res); + } + + _iface_shared.if_status_flags |= IF_STATUS_STA_UP; + _iface_shared.default_if_cfg = DEFAULT_IF_STA; + if (!_interface) { + nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + _iface_shared.iface_sta = _interface; + } else { + _stack.set_default_interface(_interface); + } + + // Initialize the Offload Manager + if (_olm != NULL) { + _olm->init_ols(_whd_emac.ifp, this); + } + + if ((_ssid == NULL) || + (strlen(_ssid) == 0)) { + return NSAPI_ERROR_PARAMETER; + } + + // setup ssid + whd_ssid_t ssid; + strncpy((char *)ssid.value, _ssid, SSID_NAME_SIZE); + ssid.value[SSID_NAME_SIZE - 1] = '\0'; + ssid.length = strlen((char *)ssid.value); + + // choose network security + whd_security_t security = whd_fromsecurity(_security); + +#if defined MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK + /* Set PSK password for WPA3_WPA2 */ + if (security == WHD_SECURITY_WPA3_WPA2_PSK) { + res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK, + strlen(MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK), WHD_SECURITY_WPA3_WPA2_PSK ); + } +#else + /* Set PSK password for WPA3_WPA2 */ + if (security == WHD_SECURITY_WPA3_WPA2_PSK) { + res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)_pass, + strlen(_pass), WHD_SECURITY_WPA3_WPA2_PSK ); + } +#endif + // join the network + for (i = 0; i < MAX_RETRY_COUNT; i++) { + res = (whd_result_t)whd_wifi_join(_whd_emac.ifp, + &ssid, + security, + (const uint8_t *)_pass, strlen(_pass)); + if (res == WHD_SUCCESS) { + break; + } + } + + if (res != WHD_SUCCESS) { + return whd_toerror(res); + } + + if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) { + whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE); + } + + // bring up + return _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK); +} + +void WhdSTAInterface::wifi_on() +{ + if (!_whd_emac.powered_up) { + if(!_whd_emac.power_up()) { + CY_ASSERT(false); + } + } +} + +nsapi_error_t WhdSTAInterface::disconnect() +{ + ScopedMutexLock lock(_iface_shared.mutex); + + if (!_interface) { + return NSAPI_STATUS_DISCONNECTED; + } + + // bring down + int err = _interface->bringdown(); + if (err) { + return err; + } + + _iface_shared.if_status_flags &= ~IF_STATUS_STA_UP; + if (_iface_shared.if_status_flags & IF_STATUS_SOFT_AP_UP) { + _iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP; + _stack.set_default_interface(_iface_shared.iface_softap); + } else { + _iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET; + } + + // leave network + whd_result_t res = whd_wifi_leave(_whd_emac.ifp); + if (res != WHD_SUCCESS) { + return whd_toerror(res); + } + whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_FALSE); + + // remove the interface added in connect + if (_interface) { + nsapi_error_t err = _stack.remove_ethernet_interface(&_interface); + if (err != NSAPI_ERROR_OK) { + return err; + } + _iface_shared.iface_sta = NULL; + } + + res = whd_wifi_deregister_event_handler(_whd_emac.ifp, sta_link_update_entry); + if (res != WHD_SUCCESS) { + return whd_toerror(res); + } + + // de-init Offload Manager + if (_olm != NULL) { + _olm->deinit_ols(); + } + + return NSAPI_ERROR_OK; +} + +int8_t WhdSTAInterface::get_rssi() +{ + int32_t rssi; + whd_result_t res; + + if (!_whd_emac.powered_up) { + if(!_whd_emac.power_up()) { + CY_ASSERT(false); + } + } + + res = (whd_result_t)whd_wifi_get_rssi(_whd_emac.ifp, &rssi); + if (res != 0) { + /* The network GT tests expect that this function should return 0 in case of an error and not assert */ + return 0; + } + + return (int8_t)rssi; +} + +static void whd_scan_handler(whd_scan_result_t **result_ptr, + void *user_data, whd_scan_status_t status) +{ + + whd_scan_userdata *data = (whd_scan_userdata *)user_data; + + /* Even after stopping scan, some results will still come as results are already present in the queue */ + if (data->scan_in_progress == false) { + return; + } + + // finished scan, either succesfully or through an abort + if (status != WHD_SCAN_INCOMPLETE) { + data->scan_in_progress = false; + data->sema->release(); + return; + } + + // can't really keep anymore scan results + if (data->count > 0 && data->offset >= data->count) { + /* We can not abort the scan as this function is getting executed in WHD context, + Note that to call any WHD API, caller function should not in WHD context */ + return; + } + + whd_scan_result_t *record = *result_ptr; + + for (unsigned int i = 0; i < data->result_buff->size(); i++) { + if (CMP_MAC((*data->result_buff)[i].BSSID.octet, record->BSSID.octet)) { + return; + } + } + + if (data->count > 0 && data->aps != NULL) { + // get ap stats + nsapi_wifi_ap ap; + uint8_t length = record->SSID.length; + if (length < sizeof(ap.ssid) - 1) { + length = sizeof(ap.ssid) - 1; + } + memcpy(ap.ssid, record->SSID.value, length); + ap.ssid[length] = '\0'; + + memcpy(ap.bssid, record->BSSID.octet, sizeof(ap.bssid)); + + ap.security = whd_tosecurity(record->security); + ap.rssi = record->signal_strength; + ap.channel = record->channel; + if (data->sres_type == SRES_TYPE_WIFI_ACCESS_POINT) { + data->aps[data->offset] = WiFiAccessPoint(ap); + } else if (data->sres_type == SRES_TYPE_WHD_ACCESS_POINT) { + WhdAccessPoint *aps_sres = static_cast(data->aps); + aps_sres[data->offset] = std::move(WhdAccessPoint(ap, record->bss_type, + record->ie_ptr, record->ie_len)); + } + } + + // store to result_buff for future duplication removal + data->result_buff->push_back(*record); + data->offset = data->result_buff->size(); +} + +int WhdSTAInterface::internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type) +{ + ScopedMutexLock lock(_iface_shared.mutex); + + // initialize wiced, this is noop if already init + if (!_whd_emac.powered_up) { + if(!_whd_emac.power_up()) { + return NSAPI_ERROR_DEVICE_ERROR; + } + } + + interal_scan_data.sema = new Semaphore(); + interal_scan_data.sres_type = sres_type; + interal_scan_data.aps = aps; + interal_scan_data.count = count; + interal_scan_data.offset = 0; + interal_scan_data.scan_in_progress = true; + interal_scan_data.result_buff = new std::vector(); + whd_result_t whd_res; + int res; + + whd_res = (whd_result_t)whd_wifi_scan(_whd_emac.ifp, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY, + NULL, NULL, NULL, NULL, whd_scan_handler, &internal_scan_result, &interal_scan_data); + if (whd_res != WHD_SUCCESS) { + res = whd_toerror(whd_res); + } else { + interal_scan_data.sema->acquire(); + res = interal_scan_data.offset; + } + + delete interal_scan_data.sema; + delete interal_scan_data.result_buff; + return res; +} + +int WhdSTAInterface::scan(WiFiAccessPoint *aps, unsigned count) +{ + return internal_scan(aps, count, SRES_TYPE_WIFI_ACCESS_POINT); +} + +int WhdSTAInterface::scan_whd(WhdAccessPoint *aps, unsigned count) +{ + return internal_scan(aps, count, SRES_TYPE_WHD_ACCESS_POINT); +} + +int WhdSTAInterface::is_interface_connected(void) +{ + if (!_whd_emac.ifp) { + return WHD_INTERFACE_NOT_UP; + } + _whd_emac.ifp->role = WHD_STA_ROLE; + if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) { + return WHD_SUCCESS; + } else { + return WHD_CONNECTION_LOST; + } +} + +int WhdSTAInterface::get_bssid(uint8_t *bssid) +{ + whd_mac_t ap_mac; + whd_result_t res = WHD_SUCCESS; + + memset(&ap_mac, 0, sizeof(ap_mac)); + _whd_emac.ifp->role = WHD_STA_ROLE; + if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) { + res = whd_wifi_get_bssid(_whd_emac.ifp, &ap_mac); + + if (res == WHD_SUCCESS) { + memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet)); + } + } + return res; +} + +int WhdSTAInterface::whd_log_print(void) +{ + return whd_wifi_print_whd_log(_whd_emac.drvp); +} + +int WhdSTAInterface::whd_log_read(char *buffer, int buffer_size) +{ + whd_result_t res = WHD_SUCCESS; + if (buffer != NULL) { + res = whd_wifi_read_wlan_log(_whd_emac.drvp, buffer, buffer_size); + } + return res; +} + +nsapi_error_t WhdSTAInterface::wifi_get_ac_params_sta(void *acp) +{ + whd_result_t res = WHD_SUCCESS; + edcf_acparam_t *ac_param = (edcf_acparam_t *)acp; + + res = whd_wifi_get_acparams(_whd_emac.ifp, ac_param); + if (res != WHD_SUCCESS) { + return res; + } + return res; +} + +int WhdSTAInterface::wifi_set_iovar_value(const char *iovar, uint32_t value) +{ + whd_result_t res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_set_iovar_value(_whd_emac.ifp, iovar, value); + return res; +} + +int WhdSTAInterface::wifi_get_iovar_value(const char *iovar, uint32_t *value) +{ + int res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_get_iovar_value(_whd_emac.ifp, iovar, value); + return res; +} +int WhdSTAInterface::wifi_set_ioctl_value(uint32_t ioctl, uint32_t value) +{ + int res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_set_ioctl_value(_whd_emac.ifp, ioctl, value); + return res; +} + +int WhdSTAInterface::wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value ) +{ + int res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_get_ioctl_value(_whd_emac.ifp, ioctl, value); + return res; +} + +int WhdSTAInterface::wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len) +{ + int res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_get_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len); + return res; +} + +int WhdSTAInterface::wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len) +{ + int res = WHD_SUCCESS; + _whd_emac.ifp->role = WHD_STA_ROLE; + res = whd_wifi_set_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len); + return res; +} + +int WhdSTAInterface::wifi_get_ifp(whd_interface_t *ifp) +{ + int res = WHD_SUCCESS; + *ifp = _whd_emac.ifp; + return res; +} + +int WhdSTAInterface::wifi_set_up(void) +{ + int res = WHD_SUCCESS; + res = whd_wifi_set_up(_whd_emac.ifp); + return res; +} + +int WhdSTAInterface::wifi_set_down(void) +{ + int res = WHD_SUCCESS; + res = whd_wifi_set_down(_whd_emac.ifp); + return res; +} + +int WhdSTAInterface::wifi_set_coex_config(whd_coex_config_t *coex_config) +{ + int res = WHD_SUCCESS; + res = whd_wifi_set_coex_config(_whd_emac.ifp, coex_config); + return res; +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h new file mode 100644 index 0000000..4dd1098 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h @@ -0,0 +1,263 @@ +/* WHD implementation of NetworkInterfaceAPI + * Copyright (c) 2017-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WHD_STA_INTERFACE_H +#define WHD_STA_INTERFACE_H + +#include "netsocket/WiFiInterface.h" +#include "netsocket/EMACInterface.h" +#include "netsocket/OnboardNetworkStack.h" +#include "WhdAccessPoint.h" +#include "whd_emac.h" +#include "whd_interface.h" +#include "whd_types_int.h" + +struct ol_desc; + +/** WhdSTAInterface class + * Implementation of the NetworkStack for the WHD + */ +class WhdSTAInterface : public WiFiInterface, public EMACInterface { +public: + class OlmInterface { + public: + /** Get the default OLM interface. */ + static OlmInterface &get_default_instance(); + + OlmInterface(struct ol_desc *list = NULL) {} + + virtual int init_ols(void *whd, void *ip) + { + return 0; + } + virtual int sleep() + { + return 0; + } + virtual int wake() + { + return 0; + } + + virtual void deinit_ols(void) {} + }; + + WhdSTAInterface( + WHD_EMAC &emac = WHD_EMAC::get_instance(), + OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(), + OlmInterface &olm = OlmInterface::get_default_instance(), + whd_interface_shared_info_t &shared = whd_iface_shared); + + static WhdSTAInterface *get_default_instance(); + + /* Turn on the wifi device*/ + void wifi_on(); + + /** Start the interface + * + * Attempts to connect to a WiFi network. Requires ssid and passphrase to be set. + * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned. + * + * @return 0 on success, negative error code on failure + */ + nsapi_error_t connect(); + + /** Start the interface + * + * Attempts to connect to a WiFi network. + * + * @param ssid Name of the network to connect to + * @param pass Security passphrase to connect to the network + * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE) + * @param channel This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED + * @return 0 on success, or error code on failure + */ + nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0); + + /** Stop the interface + * @return 0 on success, negative on failure + */ + nsapi_error_t disconnect(); + + /** Set the WiFi network credentials + * + * @param ssid Name of the network to connect to + * @param pass Security passphrase to connect to the network + * @param security Type of encryption for connection + * (defaults to NSAPI_SECURITY_NONE) + * @return 0 on success, or error code on failure + */ + nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE); + + /** Set the WiFi network channel - NOT SUPPORTED + * + * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED + * + * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0) + * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED + */ + nsapi_error_t set_channel(uint8_t channel) + { + if (channel != 0) { + return NSAPI_ERROR_UNSUPPORTED; + } + + return 0; + } + + /** Set blocking status of interface. + * Nonblocking mode unsupported. + * + * @param blocking true if connect is blocking + * @return 0 on success, negative error code on failure + */ + nsapi_error_t set_blocking(bool blocking) + { + if (blocking) { + _blocking = blocking; + return NSAPI_ERROR_OK; + } else { + return NSAPI_ERROR_UNSUPPORTED; + } + } + + /** Gets the current radio signal strength for active connection + * + * @return Connection strength in dBm (negative value) + */ + int8_t get_rssi(); + + /** Scan for available networks in WiFiAccessPoint format + * + * This function will block. + * + * @param ap Pointer to allocated array of WiFiAccessPoint format for discovered AP + * @param count Size of allocated @a res array, or 0 to only count available AP + * @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0) + * @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error + * see @a nsapi_error + */ + int scan(WiFiAccessPoint *res, unsigned count); + + /** Scan for available networks in WhdAccessPoint format + * + * This function will block. + * + * @param ap Pointer to allocated array of WhdAccessPoint format for discovered AP + * @param count Size of allocated @a res array, or 0 to only count available AP + * @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0) + * @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error + * see @a nsapi_error + */ + int scan_whd(WhdAccessPoint *res, unsigned count); + + /* is interface connected, if yes return WICED_SUCCESS else WICED_NOT_CONNECTED */ + int is_interface_connected(); + + /* get bssid of the AP if success return WICED_SUCCESS else WICED_ERROR */ + int get_bssid(uint8_t *bssid); + + /* print WHD log (this routine will malloc/free a buffer + * You need to enable printing with WHD_LOGGING_BUFFER_ENABLE + */ + int whd_log_print(void); + + /* read WHD log */ + int whd_log_read(char *buffer, int buffer_size); + + /* Get EDCF AC params */ + nsapi_error_t wifi_get_ac_params_sta(void *ac_param); + + /* get iovar value */ + int wifi_get_iovar_value(const char *iovar, uint32_t *value); + + /* set iovar value */ + int wifi_set_iovar_value(const char *iovar, uint32_t value); + + /* set ioctl value */ + int wifi_set_ioctl_value(uint32_t ioctl, uint32_t value) ; + + /* get ioctl value */ + int wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value); + + /* get ioctl buffer */ + int wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len); + + /* set ioctl buffer */ + int wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len); + + /* get WHD ifp value */ + int wifi_get_ifp(whd_interface_t *ifp); + + /* set wifi interface up */ + int wifi_set_up(void); + + /* set wifi interface down */ + int wifi_set_down(void); + + /* set wifi coex configuration */ + int wifi_set_coex_config(whd_coex_config_t *coex_config); + + /** Set Offload Manager Information + * NOTE: Only allowed while disconnected + * + * @param olm Offload Manager info structure + * @return true if completed successfully + * false if Interface is connected + */ + int set_olm(OlmInterface *olm) + { + if (get_connection_status() == NSAPI_STATUS_DISCONNECTED) { + _olm = olm; + return true; + } + return false; + } + + /** Network stack is suspended + * + * @return 0 if successful + */ + int net_suspended() + { + int ret = _olm->sleep(); + return ret; + } + + /** Network stack is resuming + * + * @return 0 if successful + */ + int net_resuming() + { + int ret = _olm->wake(); + return ret; + } + +protected: + int internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type); + +private: + char _ssid[33]; /* The longest possible name (defined in 802.11) +1 for the \0 */ + char _pass[64]; /* The longest allowed passphrase + 1 */ + nsapi_security_t _security; + WHD_EMAC &_whd_emac; + OlmInterface *_olm; + whd_interface_shared_info_t &_iface_shared; +}; + +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp new file mode 100644 index 0000000..e3c499c --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nsapi.h" +#include "lwipopts.h" +#include "WhdSoftAPInterface.h" +#include "nsapi.h" +#include "lwipopts.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "rtos.h" +#include "whd_emac.h" +#include "whd_wifi_api.h" + + +extern int whd_toerror(whd_result_t res); +extern nsapi_security_t whd_tosecurity(whd_security_t sec); +extern whd_security_t whd_fromsecurity(nsapi_security_t sec); +extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); + +static const whd_event_num_t ap_events[] = { WLC_E_LINK, WLC_E_IF, WLC_E_DEAUTH, WLC_E_DEAUTH_IND, WLC_E_DISASSOC, WLC_E_DISASSOC_IND, WLC_E_ASSOC_IND, WLC_E_REASSOC_IND, WLC_E_NONE }; + +static void *whd_default_handle_softap_events(whd_interface_t ifp, const whd_event_header_t *event_header, + const uint8_t *event_data, void *handler_user_data) +{ + whd_driver_t whd_driver = ifp->whd_driver; + + UNUSED_PARAMETER(event_header); + UNUSED_PARAMETER(event_data); + UNUSED_PARAMETER(handler_user_data); + + WHD_IOCTL_LOG_ADD_EVENT(whd_driver, event_header->event_type, event_header->flags, event_header->reason); + + if ((event_header->event_type == (whd_event_num_t)WLC_E_LINK) || + (event_header->event_type == WLC_E_IF)) { + if (osSemaphoreGetCount(whd_driver->ap_info.whd_wifi_sleep_flag) < 1) { + osStatus_t result = osSemaphoreRelease(whd_driver->ap_info.whd_wifi_sleep_flag); + if (result != osOK) { + printf("Release whd_wifi_sleep_flag ERROR: %d", result); + } + } + } + return handler_user_data; +} + + +WhdSoftAPInterface::WhdSoftAPInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, whd_interface_shared_info_t &shared) + : EMACInterface(emac, stack), + _whd_emac(emac), + _iface_shared(shared) +{ + +} + + +int WhdSoftAPInterface::start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel, + bool start_dhcp_server, const whd_custom_ie_info_t *ie_info, bool ap_sta_concur) +{ + ScopedMutexLock lock(_iface_shared.mutex); + + nsapi_error_t err; + // power up primary emac interface first + if (ap_sta_concur) { + WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE); + if (!emac_prime.power_up()) { + printf("Primary interface power up ERROR!\n"); + return NSAPI_ERROR_DEVICE_ERROR; + } + } + + // set concurrency mode and power up secondary, the bsp init is done by primary emac + _whd_emac.ap_sta_concur = ap_sta_concur; + if (!_whd_emac.power_up()) { + printf("Secondary interface power up ERROR!\n"); + return NSAPI_ERROR_DEVICE_ERROR; + } + + // setup ssid + whd_ssid_t whd_ssid; + strncpy((char *)whd_ssid.value, ssid, SSID_NAME_SIZE); + whd_ssid.value[SSID_NAME_SIZE - 1] = '\0'; + whd_ssid.length = strlen((char *)whd_ssid.value); + + // choose network security + whd_security_t whd_security = whd_fromsecurity(security); + + /* set up the AP info */ + err = whd_wifi_init_ap(_whd_emac.ifp, &whd_ssid, whd_security, (const uint8_t *)pass, + strlen(pass), channel); + if (err != NSAPI_ERROR_OK) { + printf("whd_wifi_init_ap() ERROR: %d\n", err); + return err; + } + + // update default softap interface event handler + err = unregister_event_handler(); + if (err != NSAPI_ERROR_OK) { + printf("unregister_event_handler() ERROR: %d\n", err); + return err; + } + err = register_event_handler(whd_default_handle_softap_events); + if (err != NSAPI_ERROR_OK) { + printf("register_event_handler() ERROR: %d\n", err); + return err; + } + + _iface_shared.if_status_flags |= IF_STATUS_SOFT_AP_UP; + if (!ap_sta_concur || (_iface_shared.default_if_cfg == DEFAULT_IF_NOT_SET)) { + _iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP; + } + if (!_interface) { + nsapi_error_t err = _stack.add_ethernet_interface(_whd_emac, _iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + _iface_shared.iface_softap = _interface; + } else if (_iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP) { + _stack.set_default_interface(_interface); + } + + if (ie_info) { + err = whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_ADD_CUSTOM_IE, (const uint8_t *)ie_info->oui, + ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets); + if (err != NSAPI_ERROR_OK) { + printf("whd_wifi_manage_custom_ie() ERROR: %d\n", err); + return err; + } + } + + err = whd_wifi_start_ap(_whd_emac.ifp); + if (err != NSAPI_ERROR_OK) { + printf("whd_wifi_start_ap() ERROR: %d\n", err); + return err; + } + + // Set static IP address for SoftAP and bring up + set_dhcp(false); + + if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) { + whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE); + } + + err = _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK); + if (err != NSAPI_ERROR_OK) { + printf("bringup() ERROR: %d\n", err); + } + + if (start_dhcp_server) { + _dhcp_server = std::make_unique(get_stack(), this); + if (CY_RSLT_SUCCESS != _dhcp_server->start()) { + err = NSAPI_ERROR_DHCP_FAILURE; + } + } + return err; +} + + + +int WhdSoftAPInterface::stop(void) +{ + ScopedMutexLock lock(_iface_shared.mutex); + + if (_dhcp_server && CY_RSLT_SUCCESS != _dhcp_server->stop()) { + return NSAPI_ERROR_DHCP_FAILURE; + } + _dhcp_server.reset(); + + // bring down + int err = _interface->bringdown(); + if (err) { + return err; + } + + _iface_shared.if_status_flags &= ~IF_STATUS_SOFT_AP_UP; + if ((_iface_shared.if_status_flags & IF_STATUS_STA_UP) == 0) { + _iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET; + } + + // stop softap + whd_result_t res = whd_wifi_stop_ap(_whd_emac.ifp); + if (res != WHD_SUCCESS) { + return whd_toerror(res); + } + + // remove the interface added in start + if (_interface) { + nsapi_error_t err = _stack.remove_ethernet_interface(&_interface); + if (err != NSAPI_ERROR_OK) { + return err; + } + _iface_shared.iface_softap = NULL; + } + return NSAPI_ERROR_OK; +} + +int WhdSoftAPInterface::remove_custom_ie(const whd_custom_ie_info_t *ie_info) +{ + return whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_REMOVE_CUSTOM_IE, (const uint8_t *)ie_info->oui, + ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets); +} + +int WhdSoftAPInterface::get_associated_client_list(void *client_list_buffer, uint16_t buffer_length) +{ + + return whd_wifi_get_associated_client_list(_whd_emac.ifp, client_list_buffer, buffer_length); +} + +int WhdSoftAPInterface::register_event_handler(whd_event_handler_t softap_event_handler) +{ + uint16_t ap_events_entry = _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY]; + return whd_management_set_event_handler(_whd_emac.ifp, ap_events, softap_event_handler, NULL, &ap_events_entry); +} + +int WhdSoftAPInterface::unregister_event_handler(void) +{ + return whd_wifi_deregister_event_handler(_whd_emac.ifp, _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY]); +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h new file mode 100644 index 0000000..ced7c04 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef WHD_SOFTAP_INTERFACE_H +#define WHD_SOFTAP_INTERFACE_H + +#include "netsocket/EMACInterface.h" +#include "netsocket/OnboardNetworkStack.h" +#include "whd_emac.h" +#include "CyDhcpServer.h" +#include "whd_interface.h" +#include + +/** + * Vendor IE details + */ +typedef struct { + uint8_t oui[WIFI_IE_OUI_LENGTH]; /**< Unique identifier for the IE */ + uint8_t subtype; /**< Sub-type of the IE */ + void *data; /**< Pointer to IE data */ + uint16_t length; /**< IE data length */ + uint16_t which_packets; /**< Mask of the packet in which this IE details to be included */ +} whd_custom_ie_info_t; + + + +/** WhdSoftAPInterface class + * Implementation of the SoftAPInterface for the Whd + */ +class WhdSoftAPInterface : public EMACInterface { +public: + /** Construct SoftAP interface + * @return pointer to default WhdSoftAPInterface instance + */ + WhdSoftAPInterface(WHD_EMAC &emac = WHD_EMAC::get_instance(WHD_AP_ROLE), + OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(), + whd_interface_shared_info_t &shared = whd_iface_shared); + + /** Get the default WhdSoftAPInterface instance. + * @return pointer to default WhdSoftAPInterface instance + */ + static WhdSoftAPInterface *get_default_instance(); + + /** Set static IP address for SoftAP + * + * Configures the static IP address of SoftAP + * Requires that the network is stopped. + * + * @param ip_address Null-terminated representation of the local IP address + * @param netmask Null-terminated representation of the local network mask + * @param gateway Null-terminated representation of the local gateway + * @return 0 on success, negative error code on failure + * int set_network(const char *ip_address, const char *netmask, const char *gateway); + */ + + /** Start a SoftAP + * + * @param ssid Name of the SoftAP to create + * @param pass Security passphrase for connection to SoftAP + * @param security Type of encryption for connection + * @param channel Channel for SoftAP + * @param start_dhcp_server Start dhcp server for connection + * @param whd_custom_ie Optional Custom IE + * @param ap_sta_concur Enable STA+AP concurrency mode + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel, + bool start_dhcp_server = true, const whd_custom_ie_info_t *ie_info = NULL, bool ap_sta_concur = false); + + /** + * Remove Wi-Fi custom IE + * + * @param[in] ie_info : Pointer to the structure which contains custom IE information + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int remove_custom_ie(const whd_custom_ie_info_t *ie_info); + + /** Stop the Software Access Point + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int stop(void); + + /** + * Gets information about associated clients. + * + * @note Only applicable if softAP interface is up + * + * @param[out] client_list_buffer : pointer to a buffer that will be populated with a variable length structure defined by @ref whd_maclist_t + * @param[in] buffer_length : length of the buffer + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int get_associated_client_list(void *client_list_buffer, uint16_t buffer_length); + + + /** + * Register soft AP event handler + * + * @param[in] softap_event_handler : A function pointer to the event handler + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int register_event_handler(whd_event_handler_t softap_event_handler); + + /** + * Unregister soft AP event handler + * + * @return 0 on success, or error code on failure + * see @a nsapi_error + */ + int unregister_event_handler(void); + + /** Set blocking status of interface. + * Nonblocking mode unsupported. + * + * @param blocking true if connect is blocking + * @return 0 on success, negative error code on failure + */ + nsapi_error_t set_blocking(bool blocking) + { + if (blocking) { + _blocking = blocking; + return NSAPI_ERROR_OK; + } else { + return NSAPI_ERROR_UNSUPPORTED; + } + } + +protected: + WHD_EMAC &_whd_emac; + std::unique_ptr _dhcp_server; + whd_interface_shared_info_t &_iface_shared; +}; + +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h new file mode 100644 index 0000000..5234065 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h @@ -0,0 +1,65 @@ +/* + * Copyright 2019 Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef INCLUDED_EMAC_EAPOL_H_ +#define INCLUDED_EMAC_EAPOL_H_ + +#include "whd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** + * Macros + ******************************************************/ + +/****************************************************** + * Constants + ******************************************************/ +#define EAPOL_PACKET_TYPE (0x888E) + +/****************************************************** + * Enumerations + ******************************************************/ + +/****************************************************** + * Type Definitions + ******************************************************/ + +typedef whd_buffer_t whd_eapol_packet_t; + +typedef void (*eapol_packet_handler_t)(whd_interface_t interface, whd_buffer_t buffer); + +/****************************************************** + * Structures + ******************************************************/ + +/****************************************************** + * Global Variables + ******************************************************/ + +/****************************************************** + * Function Declarations + ******************************************************/ +whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler); +void emac_unregister_eapol_packet_handler(void); + +#ifdef __cplusplus +} /* extern "C" */ +#endif +#endif /* ifndef INCLUDED_EMAC_EAPOL_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp new file mode 100644 index 0000000..138bd8b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" +#include "whd_emac.h" +#include "lwip/etharp.h" +#include "lwip/ethip6.h" +#include "mbed_shared_queues.h" +#include "whd_wlioctl.h" +#include "whd_buffer_api.h" +#include "cybsp_wifi.h" +#include "emac_eapol.h" +#include "cy_result.h" + +#define NULL_MAC(a) ( ( ( ( (unsigned char *)a )[0] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[1] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[2] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[3] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[4] ) == 0 ) && \ + ( ( ( (unsigned char *)a )[5] ) == 0 ) ) + +extern "C" +{ + eapol_packet_handler_t emac_eapol_packet_handler = NULL; + void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); +} // extern "C" + +WHD_EMAC::WHD_EMAC(whd_interface_role_t role, const uint8_t *mac_addr) + : interface_type(role) +{ + if (mac_addr) { + set_hwaddr(mac_addr); + } +} + +WHD_EMAC &WHD_EMAC::get_instance(whd_interface_role_t role, const uint8_t *mac_addr) +{ + static WHD_EMAC emac_sta(WHD_STA_ROLE, mac_addr); + static WHD_EMAC emac_ap(WHD_AP_ROLE, mac_addr); + return role == WHD_AP_ROLE ? emac_ap : emac_sta; +} + +uint32_t WHD_EMAC::get_mtu_size() const +{ + return WHD_PAYLOAD_MTU; +} + +uint32_t WHD_EMAC::get_align_preference() const +{ + return 0; +} + +void WHD_EMAC::add_multicast_group(const uint8_t *addr) +{ + memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet)); + whd_wifi_register_multicast_address(ifp, &multicast_addr); +} + +void WHD_EMAC::remove_multicast_group(const uint8_t *addr) +{ + whd_wifi_unregister_multicast_address(ifp, &multicast_addr); +} + +void WHD_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void WHD_EMAC::power_down() +{ + if (powered_up) { + powered_up = false; + whd_wifi_off(ifp); + whd_deinit(ifp); + } +} + +bool WHD_EMAC::power_up() +{ + if (!powered_up) { + cy_rslt_t res = CY_RSLT_SUCCESS; + if (ap_sta_concur && interface_type == WHD_AP_ROLE) { + WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE); + if (NULL_MAC(unicast_addr.octet)) { + emac_prime.get_hwaddr(unicast_addr.octet); + // Generated mac will set locally administered bit 1 of first byte + unicast_addr.octet[0] |= (1 << 1); + } + // Note: This assumes that the primary interface initializes the + // wifi driver and turns on the wifi chip. + res = cybsp_wifi_init_secondary(&ifp /* Out */, &unicast_addr); + } else { + WHD_EMAC &emac_other = WHD_EMAC::get_instance(interface_type == WHD_STA_ROLE ? WHD_AP_ROLE : + WHD_STA_ROLE); + if (!emac_other.powered_up) { + res = cybsp_wifi_init_primary(&ifp /* OUT */); + } else { + ifp = emac_other.ifp; + } + } + + if (CY_RSLT_SUCCESS == res) { + drvp = cybsp_get_wifi_driver(); + powered_up = true; + if (link_state && emac_link_state_cb) { + emac_link_state_cb(link_state); + } + } else { + return false; + } + } + return true; +} + +bool WHD_EMAC::get_hwaddr(uint8_t *addr) const +{ + if (!NULL_MAC(unicast_addr.octet)) { + memcpy(addr, unicast_addr.octet, sizeof(unicast_addr.octet)); + } else { + whd_mac_t mac; + whd_result_t res = whd_wifi_get_mac_address(ifp, &mac); + MBED_ASSERT(res == WHD_SUCCESS); + memcpy(addr, mac.octet, sizeof(mac.octet)); + } + return true; +} + +void WHD_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(unicast_addr.octet, addr, sizeof(unicast_addr.octet)); +} + +uint8_t WHD_EMAC::get_hwaddr_size() const +{ + whd_mac_t mac; + return sizeof(mac.octet); +} + +void WHD_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void WHD_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void WHD_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +bool WHD_EMAC::link_out(emac_mem_buf_t *buf) +{ + uint16_t offset = 64; + whd_buffer_t buffer; + + uint16_t size = memory_manager->get_total_len(buf); + + whd_result_t res = whd_host_buffer_get(drvp, &buffer, WHD_NETWORK_TX, size + offset, WHD_TRUE); + if (res != WHD_SUCCESS) { + memory_manager->free(buf); + return true; + } + MBED_ASSERT(res == WHD_SUCCESS); + + whd_buffer_add_remove_at_front(drvp, &buffer, offset); + + void *dest = whd_buffer_get_current_piece_data_pointer(drvp, buffer); + memory_manager->copy_from_buf(dest, size, buf); + + if (activity_cb) { + activity_cb(true); + } + whd_network_send_ethernet_data(ifp, buffer); + memory_manager->free(buf); + return true; +} + +void WHD_EMAC::get_ifname(char *name, uint8_t size) const +{ + switch (interface_type) { + case WHD_STA_ROLE: + memcpy(name, "st", size); + break; + case WHD_AP_ROLE: + memcpy(name, "ap", size); + break; + default: + memcpy(name, "wh", size); + } +} + +void WHD_EMAC::set_activity_cb(mbed::Callback cb) +{ + activity_cb = cb; +} + +extern "C" +{ + + static void emac_receive_eapol_packet(whd_interface_t interface, whd_buffer_t buffer) + { + if (buffer != NULL) { + if (emac_eapol_packet_handler != NULL) { + + emac_eapol_packet_handler(interface, buffer); + } else { + whd_buffer_release(interface->whd_driver, buffer, WHD_NETWORK_RX); + } + } + } + + whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler) + { + + if (emac_eapol_packet_handler == NULL) { + emac_eapol_packet_handler = eapol_packet_handler; + return WHD_SUCCESS; + } + + return WHD_HANDLER_ALREADY_REGISTERED; + } + + void emac_unregister_eapol_packet_handler(void) + { + emac_eapol_packet_handler = NULL; + } + + void cy_network_process_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer) + { + emac_mem_buf_t *mem_buf = NULL; + + WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role); + + if (!emac.powered_up || !emac.emac_link_input_cb) { + // ignore any trailing packets + whd_buffer_release(emac.drvp, buffer, WHD_NETWORK_RX); + return; + } + + uint8_t *data = whd_buffer_get_current_piece_data_pointer(emac.drvp, buffer); + + uint16_t size = whd_buffer_get_current_piece_size(emac.drvp, buffer); + + + if (size > WHD_ETHERNET_SIZE) { + + uint16_t ethertype; + + ethertype = (uint16_t)(data[12] << 8 | data[13]); + + if (ethertype == EAPOL_PACKET_TYPE) { + + /* pass it to the EAP layer, but do not release the packet */ + emac_receive_eapol_packet(ifp, buffer); + + } else { + mem_buf = buffer; + if (emac.activity_cb) { + emac.activity_cb(false); + } + emac.emac_link_input_cb(mem_buf); + } + } + } + + void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up) + { + WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role); + + emac.link_state = state_up; + if (emac.emac_link_state_cb) { + emac.emac_link_state_cb(state_up); + } + } + +} // extern "C" diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h new file mode 100644 index 0000000..d50486e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WHD_EMAC_H_ +#define WHD_EMAC_H_ + +#include "EMAC.h" +#include "EMACInterface.h" +#include "WiFiInterface.h" +#include "whd_int.h" + +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class WHD_EMAC : public EMAC { +public: + WHD_EMAC(whd_interface_role_t itype = WHD_STA_ROLE, const uint8_t *mac_addr = NULL); + + static WHD_EMAC &get_instance(whd_interface_role_t role = WHD_STA_ROLE, const uint8_t *mac_addr = NULL); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + /** Set callback to receive EMAC activity events + * + * @param activity_cb The callback for activity events + */ + virtual void set_activity_cb(mbed::Callback activity_cb); + + emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb = NULL; + EMACMemoryManager *memory_manager; + bool powered_up = false; + bool link_state = false; + bool ap_sta_concur = false; + whd_interface_role_t interface_type; + whd_driver_t drvp = NULL; + whd_interface_t ifp = NULL; + whd_mac_t unicast_addr; + whd_mac_t multicast_addr; + mbed::Callback activity_cb; +}; + +#endif /* WHD_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp new file mode 100644 index 0000000..6798817 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018-2019, Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WhdSTAInterface.h" +#include "WhdSoftAPInterface.h" +#include "whd_interface.h" + +whd_interface_shared_info_t whd_iface_shared; + +WiFiInterface *WiFiInterface::get_target_default_instance() +{ + static WhdSTAInterface wifi; + return &wifi; +} + +WhdSoftAPInterface *WhdSoftAPInterface::get_default_instance() +{ + static WhdSoftAPInterface softap; + return &softap; +} diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h new file mode 100644 index 0000000..73dbe30 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h @@ -0,0 +1,51 @@ +/* WHD implementation of NetworkInterfaceAPI + * Copyright (c) 2017-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WHD_INTERFACE_H +#define WHD_INTERFACE_H + +#include "rtos/Mutex.h" +#include "OnboardNetworkStack.h" + +/** WhdSTAInterface class + * Shared information + */ +#define IF_STATUS_ALL_IF_DOWN 0x0 +#define IF_STATUS_STA_UP 0x1 +#define IF_STATUS_SOFT_AP_UP 0x2 + +enum whd_default_interface_config +{ + DEFAULT_IF_NOT_SET, + DEFAULT_IF_STA, + DEFAULT_IF_SOFT_AP +}; + +struct whd_interface_shared_info_t { + rtos::Mutex mutex; + whd_default_interface_config default_if_cfg; + uint32_t if_status_flags; + OnboardNetworkStack::Interface *iface_sta; + OnboardNetworkStack::Interface *iface_softap; + whd_interface_shared_info_t() : default_if_cfg(DEFAULT_IF_NOT_SET), if_status_flags(IF_STATUS_ALL_IF_DOWN), + iface_sta(NULL), iface_softap(NULL) + {} +}; + +extern whd_interface_shared_info_t whd_iface_shared; + +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h new file mode 100644 index 0000000..7d7e48f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h @@ -0,0 +1,135 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WICED_NETWORK_H +#define WICED_NETWORK_H +#include "w_dtls_types.h" +#include "wiced_result.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/****************************************************** + * Macros + ******************************************************/ + +#define IP_HANDLE(interface) (wiced_ip_handle[(interface) & 3]) + +/****************************************************** + * Constants + ******************************************************/ + +#define WICED_MAXIMUM_NUMBER_OF_SOCKETS_WITH_CALLBACKS (1) +#define WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS (1) + +#define SIZE_OF_ARP_ENTRY sizeof(1) + +#define IP_STACK_SIZE (2 * 1024) +#define ARP_CACHE_SIZE (6 * SIZE_OF_ARP_ENTRY) +#define DHCP_STACK_SIZE (1024) +#define WICED_PKT_SIZE (1500) +#define WICED_ANY_PORT (0) + +/****************************************************** + * Enumerations + ******************************************************/ + +typedef enum { + WICED_SOCKET_ERROR +} wiced_socket_state_t; + +/****************************************************** + * Type Definitions + ******************************************************/ +typedef struct { + uint8_t *payload; + uint16_t len; + uint16_t pktstart; +} wiced_packet_t; + + +//typedef NOOS_DUMMY wiced_tls_context_type_t; +//typedef NOOS_DUMMY wiced_tls_context_t; +//typedef NOOS_DUMMY wiced_tls_session_t; +//typedef NOOS_DUMMY wiced_tls_certificate_t; +//typedef NOOS_DUMMY wiced_tls_endpoint_type_t; +typedef void *NOOS_TCP_SOCKET; + +/****************************************************** + * Structures + ******************************************************/ + +typedef struct wiced_tcp_socket_struct wiced_tcp_socket_t; +typedef struct wiced_udp_socket_struct wiced_udp_socket_t; + +typedef wiced_result_t (*wiced_tcp_socket_callback_t)(wiced_tcp_socket_t *socket, void *arg); +typedef wiced_result_t (*wiced_udp_socket_callback_t)(wiced_udp_socket_t *socket, void *arg); + +struct wiced_udp_socket_struct { + wiced_dtls_context_t *dtls_context; + struct { + wiced_tcp_socket_callback_t disconnect; + wiced_tcp_socket_callback_t receive; + wiced_tcp_socket_callback_t connect; + } callbacks; + void *callback_arg; +}; + +struct wiced_tcp_socket_struct { + NOOS_TCP_SOCKET socket; + wiced_tls_context_t *tls_context; + wiced_bool_t context_malloced; + struct { + wiced_tcp_socket_callback_t disconnect; + wiced_tcp_socket_callback_t receive; + wiced_tcp_socket_callback_t connect; + } callbacks; + void *callback_arg; +}; + +typedef struct { + wiced_tcp_socket_t socket[WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS]; + int interface; + uint16_t port; + wiced_tls_identity_t *tls_identity; +} wiced_tcp_server_t; + +/****************************************************** + * Global Variables + ******************************************************/ +typedef struct { + int dummy; +} NOOS_IP; +typedef struct { + int dummy; +} NOOS_PACKET_POOL; +/* + * Note: These objects are for internal use only! + */ +extern NOOS_IP wiced_ip_handle [3]; +extern NOOS_PACKET_POOL wiced_packet_pools [2]; /* 0=TX, 1=RX */ + +/****************************************************** + * Function Declarations + ******************************************************/ + + +#ifdef __cplusplus +} /*extern "C" */ +#endif +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp new file mode 100644 index 0000000..baf2f26 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp @@ -0,0 +1,405 @@ +#include "CyDhcpServer.h" + +#if defined(__cplusplus) +extern "C" +{ +#endif + +typedef struct DHCP_options_table_s { + uint8_t code; + uint32_t length; /* 0x80000000 means variable */ + const char *name; +} dhcp_options_table_t; + +static dhcp_options_table_t dhcp_options_lookup_table[] = { + { 0, 0, "Pad" }, + { 1, 4, "Subnet Mask" }, + { 2, 4, "Time Offset" }, + { 3, 0, "Router" }, + { 4, 0, "Time Server" }, + { 5, 0, "Name Server" }, + { 6, 0, "Domain Server" }, + { 7, 0, "Log Server" }, + { 8, 0, "Quotes Server" }, + { 9, 0, "LPR Server" }, + { 10, 0, "Impress Server" }, + { 11, 0, "RLP Server" }, + { 12, 0, "Hostname" }, + { 13, 2, "Boot File Size" }, + { 14, 0, "Merit Dump File" }, + { 15, 0, "Domain Name" }, + { 16, 0, "Swap Server" }, + { 17, 0, "Root Path" }, + { 18, 0, "Extension File" }, + { 19, 1, "Forward On/Off" }, + { 20, 1, "SrcRte On/Off" }, + { 21, 0, "Policy Filter" }, + { 22, 2, "Max DG Assembly" }, + { 23, 1, "Default IP TTL" }, + { 24, 4, "MTU Timeout" }, + { 25, 0, "MTU Plateau" }, + { 26, 2, "MTU Interface" }, + { 27, 1, "MTU Subnet" }, + { 28, 4, "Broadcast Address" }, + { 29, 1, "Mask Discovery" }, + { 30, 1, "Mask Supplier" }, + { 31, 1, "Router Discovery" }, + { 32, 4, "Router Request" }, + { 33, 0, "Static Route" }, + { 34, 1, "Trailers" }, + { 35, 4, "ARP Timeout" }, + { 36, 1, "Ethernet" }, + { 37, 1, "Default TCP TTL" }, + { 38, 4, "Keepalive Time" }, + { 39, 1, "Keepalive Data" }, + { 40, 0, "NIS Domain" }, + { 41, 0, "NIS Servers" }, + { 42, 0, "NTP Servers" }, + { 43, 0, "Vendor Specific" }, + { 44, 0, "NETBIOS Name Srv" }, + { 45, 0, "NETBIOS Dist Srv" }, + { 46, 1, "NETBIOS Node Type" }, + { 47, 0, "NETBIOS Scope" }, + { 48, 0, "X Window Font" }, + { 49, 0, "X Window Manager" }, + { 50, 4, "Address Request" }, + { 51, 4, "Address Time" }, + { 52, 1, "Overload" }, + { 53, 1, "DHCP Msg Type" }, + { 54, 4, "DHCP Server Id" }, + { 55, 0, "Parameter List" }, + { 56, 0, "DHCP Message" }, + { 57, 2, "DHCP Max Msg Size" }, + { 58, 4, "Renewal Time" }, + { 59, 4, "Rebinding Time" }, + { 60, 0, "Class Id" }, + { 61, 0, "Client Id" }, + { 62, 0, "NetWare/IP Domain" }, + { 63, 0, "NetWare/IP Option" }, + { 64, 0, "NIS-Domain-Name" }, + { 65, 0, "NIS-Server-Addr" }, + { 66, 0, "Server-Name" }, + { 67, 0, "Bootfile-Name" }, + { 68, 0, "Home-Agent-Addrs" }, + { 69, 0, "SMTP-Server" }, + { 70, 0, "POP3-Server" }, + { 71, 0, "NNTP-Server" }, + { 72, 0, "WWW-Server" }, + { 73, 0, "Finger-Server" }, + { 74, 0, "IRC-Server" }, + { 75, 0, "StreetTalk-Server" }, + { 76, 0, "STDA-Server" }, + { 77, 0, "User-Class" }, + { 78, 0, "Directory Agent" }, + { 79, 0, "Service Scope" }, + { 80, 0, "Rapid Commit" }, + { 81, 0, "Client FQDN" }, + { 82, 0, "Relay Agent Information" }, + { 83, 0, "iSNS" }, + { 85, 0, "NDS Servers" }, + { 86, 0, "NDS Tree Name" }, + { 87, 0, "NDS Context" }, + { 88, 0x80000000, "BCMCS Controller Domain Name list" }, + { 89, 0x80000000, "BCMCS Controller IPv4 address option" }, + { 90, 0, "Authentication" }, + { 91, 0x80000000, "client-last-transaction-time option" }, + { 92, 0x80000000, "associated-ip option" }, + { 93, 0, "Client System" }, + { 94, 0, "Client NDI" }, + { 95, 0, "LDAP" }, + { 97, 0, "UUID/GUID" }, + { 98, 0, "User-Auth" }, + { 99, 0x80000000, "GEOCONF_CIVIC" }, + {100, 0, "PCode" }, + {101, 0, "TCode" }, + {109, 16, "OPTION_DHCP4O6_S46_SADDR" }, + {112, 0, "Netinfo Address" }, + {113, 0, "Netinfo Tag" }, + {114, 0, "URL" }, + {116, 0, "Auto-Config" }, + {117, 0, "Name Service Search" }, + {118, 4, "Subnet Selection Option" }, + {119, 0, "Domain Search" }, + {120, 0, "SIP Servers DHCP Option" }, + {121, 0, "Classless Static Route Option" }, + {122, 0, "CCC" }, + {123, 16, "GeoConf Option" }, + {124, 0, "V-I Vendor Class" }, + {125, 0, "V-I Vendor-Specific Information" }, + {128, 0, "Etherboot signature. 6 bytes: E4:45:74:68:00:00" }, + {129, 4, "Call Server IP address" }, + {130, 0x80000000, "Ethernet interface. Variable" }, + {131, 0, "Remote statistics server IP address" }, + {132, 0, "IEEE 802.1Q VLAN ID" }, + {133, 0, "IEEE 802.1D/p Layer 2 Priority" }, + {134, 0, "Diffserv Code Point (DSCP) for" }, + {135, 0, "HTTP Proxy for phone-specific" }, + {136, 0, "OPTION_PANA_AGENT" }, + {137, 0, "OPTION_V4_LOST" }, + {138, 0, "OPTION_CAPWAP_AC_V4" }, + {139, 0, "OPTION-IPv4_Address-MoS" }, + {140, 0, "OPTION-IPv4_FQDN-MoS" }, + {141, 0, "SIP UA Configuration Service Domains" }, + {142, 0, "OPTION-IPv4_Address-ANDSF" }, + {143, 0, "OPTION_V4_SZTP_REDIRECT" }, + {144, 16, "GeoLoc" }, + {145, 1, "FORCERENEW_NONCE_CAPABLE" }, + {146, 0, "RDNSS Selection" }, + {151, 0x80000000, "N+1 status-code" }, + {152, 4, "base-time" }, + {153, 4, "start-time-of-state" }, + {154, 4, "query-start-time" }, + {155, 4, "query-end-time" }, + {156, 1, "dhcp-state" }, + {157, 1, "data-source" }, + {158, 0x80000000, " Variable; the minimum length is 5. OPTION_V4_PCP_SERVER" }, + {159, 4, "OPTION_V4_PORTPARAMS" }, + {160, 0, "DHCP Captive-Portal" }, + {161, 0x80000000, "(variable) OPTION_MUD_URL_V4" }, + {208, 4, "PXELINUX Magic" }, + {209, 0, "Configuration File" }, + {210, 0, "Path Prefix" }, + {211, 4, "Reboot Time" }, + {212, 0x80000000, "18+ N OPTION_6RD" }, + {213, 0, "OPTION_V4_ACCESS_DOMAIN" }, + {220, 0, "Subnet Allocation Option" }, +}; + +#define isprint(c) ((c) >= 0x20 && (c) < 0x7f) +int hex_dump_print(const void *data_ptr, uint16_t length, int show_ascii) +{ + uint8_t *data = (uint8_t *)data_ptr; + uint8_t *char_ptr; + int i, count; + if ((data == NULL) || (length == 0)) { + return -1; + } + count = 0; + char_ptr = data; + while (length > 0) { + i = 0; + while ((length > 0) && (i < 16)) { + printf(" %02x", *data); + i++; + data++; + length--; + count++; + } + + if (show_ascii != 0) { + int fill = 16 - i; + /* fill in for < 16 */ + while (fill > 0) { + printf(" "); + fill--; + } + /* space between numbers and chars */ + printf(" "); + while (i > 0) { + printf("%c", (isprint(*char_ptr) ? *char_ptr : '.')); + char_ptr++; + i--; + } + } + printf("\n"); + } + return count; +} + + +void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title) +{ + uint8_t *ptr; + if (title != NULL) { + printf("%s:\n", title); + } + + printf("Opcode :%2d : %s\n", header->Opcode, (header->Opcode == 1) ? "Request" : (header->Opcode == 2) ? "Reply" : "Unknown"); + printf("HwType :%2d : %s\n", header->HwType, (header->HwType == 1) ? "Ethernet" : "Unknown"); + printf("HwLength : : %d\n", header->HwLen); + printf("Hops : : %d\n", header->Hops); + printf("TransactionId : : 0x%lx\n", header->TransactionId); + printf("Elapsed time : : %d\n", header->SecsElapsed); + printf("Flags : : 0x%08x\n", header->Flags); + uint8_t *ip_ptr = (uint8_t *)&header->ClientIpAddr; + printf("from client IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); + ip_ptr = (uint8_t *)&header->YourIpAddr; + printf("from us YOUR IP: : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); + ip_ptr = (uint8_t *)&header->ServerIpAddr; + printf("DHCP server IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); + ip_ptr = (uint8_t *)&header->GatewayIpAddr; + printf("gateway IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); + + printf("Client MAC : :"); + hex_dump_print(header->ClientHwAddr, 16, 0); + ip_ptr = (uint8_t *)&header->MagicCookie; + printf("Magic : : %2x %2x %2x %2x\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); + + printf("Options :\n"); + ptr = (uint8_t *)header->Options; + printf("Hex Dump:\n"); + hex_dump_print(ptr, 64, 1); + printf("\n"); + + while ((ptr != NULL) && (*ptr != DHCP_END_OPTION_CODE) && ((uint32_t)(ptr - &header->Options[0]) < datalen)) { + int len; + switch (*ptr) { + case DHCP_SUBNETMASK_OPTION_CODE: // (1) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d SUBNET MASK : ", DHCP_SUBNETMASK_OPTION_CODE, len); + hex_dump_print(ptr, len, 1); + ptr += len; + break; + case DHCP_ROUTER_OPTION_CODE: // (3) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d ROUTER : ", DHCP_ROUTER_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_DNS_SERVER_OPTION_CODE: // (6) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d DNS SERVER : ", DHCP_DNS_SERVER_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_HOST_NAME_OPTION_CODE: + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d HOST NAME : ", DHCP_HOST_NAME_OPTION_CODE, len); + hex_dump_print(ptr, len, 1); + ptr += len; + break; + case DHCP_MTU_OPTION_CODE: // (26) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d MTU : ", DHCP_MTU_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE: // (50) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d REQUESTED IP : ", DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_LEASETIME_OPTION_CODE: // (51) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d LEASE TIME : ", DHCP_LEASETIME_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_MESSAGETYPE_OPTION_CODE: { // (53) + ptr++; + len = *ptr++; + int code = *ptr; + printf(" Code:%d Length:%d MESSAGE : ", DHCP_MESSAGETYPE_OPTION_CODE, len); + switch (code) { + case 1: + printf(" %d -- DHCP DISCOVER\n", code); + break; + case 2: + printf(" %d -- DHCP OFFER\n", code); + break; + case 3: + printf(" %d -- DHCP REQUEST\n", code); + break; + case 4: + printf(" %d -- DHCP DECLINE\n", code); + break; + case 5: + printf(" %d -- DHCP ACK\n", code); + break; + case 6: + printf(" %d -- DHCP NACK\n", code); + break; + case 7: + printf(" %d -- DHCP RELEASE\n", code); + break; + case 8: + printf(" %d -- DHCP INFORM\n", code); + break; + default: + printf(" %d -- INVALID\n", code); + break; + } + ptr += len; + break; + } + case DHCP_SERVER_IDENTIFIER_OPTION_CODE: // (54) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d SERVER ID : ", DHCP_SERVER_IDENTIFIER_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + ptr += len; + break; + case DHCP_PARAM_REQUEST_LIST_OPTION_CODE: +// 9.8. Parameter Request List +// +// This option is used by a DHCP client to request values for specified +// configuration parameters. The list of requested parameters is +// specified as n octets, where each octet is a valid DHCP option code +// as defined in this document. +// +// The client MAY list the options in order of preference. The DHCP +// server is not required to return the options in the requested order, +// but MUST try to insert the requested options in the order requested +// by the client. +// +// The code for this option is 55. Its minimum length is 1. +// +// Code Len Option Codes +// +-----+-----+-----+-----+--- +// | 55 | n | c1 | c2 | ... +// +-----+-----+-----+-----+--- + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d PARAM REQ : ", DHCP_PARAM_REQUEST_LIST_OPTION_CODE, len); + hex_dump_print(ptr, len, 0); + { + int i; + for (i = 0; i < len; i++) { + uint8_t sub_code; + sub_code = *ptr++; + + uint32_t lookup_index; + uint32_t max_lookup = (sizeof(dhcp_options_lookup_table) / sizeof(dhcp_options_lookup_table[0])); + for (lookup_index = 0; lookup_index < max_lookup; lookup_index++) { + if (dhcp_options_lookup_table[lookup_index].code == sub_code) { + uint32_t length = dhcp_options_lookup_table[lookup_index].length; + if (length != 0) { + /* length is variable, in the length field ? */ + length = *ptr; + } + printf(" Code:%3d : %s\n", dhcp_options_lookup_table[lookup_index].code, dhcp_options_lookup_table[lookup_index].name); + break; + } + } + if (lookup_index >= max_lookup) { + printf(" Code:%3d : UNKNOWN\n", dhcp_options_lookup_table[lookup_index].code); + } + } + } + break; + case DHCP_WPAD_OPTION_CODE: // (252) + ptr++; + len = *ptr++; + printf(" Code:%d Length:%d WPAD : ", DHCP_WPAD_OPTION_CODE, len); + hex_dump_print(ptr, len, 1); + ptr += len; + break; + + default: + ptr++; + break; + } + } +} + +#if defined(__cplusplus) +} +#endif diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c new file mode 100644 index 0000000..9a92391 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cynetwork_utils.h" + +uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length) +{ + uint8_t digits_left; + char buffer[] = "0000000000"; + + if (output == NULL) { + return 0; + } + + max_length = (uint8_t) MIN(max_length, sizeof(buffer)); + digits_left = max_length; + while ((value != 0) && (digits_left != 0)) { + --digits_left; + buffer[digits_left] = (char)((value % 10) + '0'); + value = value / 10; + } + + digits_left = (uint8_t) MIN((max_length - min_length), digits_left); + memcpy(output, &buffer[digits_left], (size_t)(max_length - digits_left)); + + /* Add terminating null */ + output[(max_length - digits_left)] = '\x00'; + + return (uint8_t)(max_length - digits_left); +} + +void ipv4_to_string(char buffer[16], uint32_t ipv4_address) +{ + uint8_t *ip = (uint8_t *)&ipv4_address; + + /* unsigned_to_decimal_string() null-terminates the string + * Save the original last character and replace it */ + char last_char = buffer[16]; + unsigned_to_decimal_string(ip[0], &buffer[0], 3, 3); + buffer[3] = '.'; + unsigned_to_decimal_string(ip[1], &buffer[4], 3, 3); + buffer[7] = '.'; + unsigned_to_decimal_string(ip[2], &buffer[8], 3, 3); + buffer[11] = '.'; + unsigned_to_decimal_string(ip[3], &buffer[12], 3, 3); + buffer[16] = last_char; +} + +uint32_t string_to_ipv4(const char *buffer) +{ + uint32_t temp = 0; + int char_count = 0; + const char *ptr = buffer; + + while ((ptr != NULL) && (*ptr != 0) && (char_count++ < 16)) { + uint8_t byte = 0; + while ((*ptr != 0) && (*ptr != '.') && (char_count++ < 16)) { + byte *= 10; + if ((*ptr >= '0') && (*ptr <= '9')) { + byte += (*ptr - '0'); + } else { + break; + } + ptr++; + } + temp <<= 8; + temp |= byte; + if (*ptr == '.') { + ptr++; /* skip '.' */ + } + } + return temp; +} + diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h new file mode 100644 index 0000000..0a7bdc0 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef MIN +extern int MIN(/*@sef@*/ int x, /*@sef@*/ int y); /* LINT : This tells lint that the parameter must be side-effect free. i.e. evaluation does not change any values (since it is being evaulated more than once */ +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#endif /* ifndef MIN */ + +#define FX_IPTYPE_IPV4 (0) +#define FX_IPTYPE_IPV6 (1) + +typedef union { + uint32_t addr; + uint8_t addrs[4]; +} cy_ip_addr_v4_t; + +typedef struct { + uint32_t addr[4]; +} cy_ip_addr_v6_t; + +typedef struct { + uint8_t type; + union { + cy_ip_addr_v4_t addrv4; + cy_ip_addr_v6_t addrv6; + }; +} cy_ip_addr_t; + +/** + * Structure for storing a MAC address (Wi-Fi Media Access Control address). + */ +typedef struct { + uint8_t octet[6]; /**< Unique 6-byte MAC address */ +} cy_mac_addr_t; + +/** + * Converts a unsigned long int to a decimal string + * + * @param value[in] : The unsigned long to be converted + * @param output[out] : The buffer which will receive the decimal string + * @param min_length[in] : the minimum number of characters to output (zero padding will apply if required). + * @param max_length[in] : the maximum number of characters to output (up to 10 ). There must be space for terminating NULL. + * + * @note: A terminating NULL is added. Wnsure that there is space in the buffer for this. + * + * @return the number of characters returned (excluding terminating null) + * + */ +uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length); + +/** + * Convert a IPv4 address to a string + * + * @note: String is 16 bytes including terminating null + * + * @param[out] buffer : Buffer which will recieve the IPv4 string + * @param[in] ipv4_address : IPv4 address to convert + */ +void ipv4_to_string(char buffer[16], uint32_t ipv4_address); + +/** + * Convert a IPv4 address to a string + * + * @note: String is 16 bytes including terminating null + * + * @param[in] buffer : Buffer which has the IPv4 string + * @return ipv4_address (0 on failure) + */ +uint32_t string_to_ipv4(const char *buffer); + +#if defined(__cplusplus) +} +#endif diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c b/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c new file mode 100644 index 0000000..bdd51be --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_port.h" +#include "fsl_sysmpu.h" + +/* Initialize the region 1, master 0, 1, 2, 3 - core access rights supervisior r/w/x , user r/w/x. */ +sysmpu_rwxrights_master_access_control_t right = +{ + kSYSMPU_SupervisorEqualToUsermode, + kSYSMPU_UserReadWriteExecute, +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + false, +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +void kinetis_init_eth_hardware(void) +{ + port_pin_config_t configENET = {0}; + sysmpu_region_config_t regConfig; + sysmpu_config_t config; + + memset(®Config, 0, sizeof(sysmpu_region_config_t)); + memset(&config, 0, sizeof(sysmpu_config_t)); + + regConfig.regionNum = 1; + regConfig.startAddress = 0U; + regConfig.endAddress = 0xFFFFFFFFU; + regConfig.accessRights1[0] = right; + regConfig.accessRights1[1] = right; + regConfig.accessRights1[2] = right; + regConfig.accessRights1[3] = right; + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + regConfig.processIdentifier = 1U; + regConfig.processIdMask = 0U; +#endif + + config.regionConfig = regConfig; + SYSMPU_Init(SYSMPU, &config); + + CLOCK_EnableClock(kCLOCK_PortC); + CLOCK_EnableClock(kCLOCK_PortB); + /* Affects PORTC_PCR16 register */ + PORT_SetPinMux(PORTC, 16u, kPORT_MuxAlt4); + /* Affects PORTC_PCR17 register */ + PORT_SetPinMux(PORTC, 17u, kPORT_MuxAlt4); + /* Affects PORTC_PCR18 register */ + PORT_SetPinMux(PORTC, 18u, kPORT_MuxAlt4); + /* Affects PORTC_PCR19 register */ + PORT_SetPinMux(PORTC, 19u, kPORT_MuxAlt4); + /* Affects PORTB_PCR1 register */ + PORT_SetPinMux(PORTB, 1u, kPORT_MuxAlt4); + + configENET.openDrainEnable = kPORT_OpenDrainEnable; + configENET.mux = kPORT_MuxAlt4; + configENET.pullSelect = kPORT_PullUp; + /* Ungate the port clock */ + CLOCK_EnableClock(kCLOCK_PortA); + /* Affects PORTB_PCR0 register */ + PORT_SetPinConfig(PORTB, 0u, &configENET); + + /* Affects PORTA_PCR13 register */ + PORT_SetPinMux(PORTA, 13u, kPORT_MuxAlt4); + /* Affects PORTA_PCR12 register */ + PORT_SetPinMux(PORTA, 12u, kPORT_MuxAlt4); + /* Affects PORTA_PCR14 register */ + PORT_SetPinMux(PORTA, 14u, kPORT_MuxAlt4); + /* Affects PORTA_PCR5 register */ + PORT_SetPinMux(PORTA, 5u, kPORT_MuxAlt4); + /* Affects PORTA_PCR16 register */ + PORT_SetPinMux(PORTA, 16u, kPORT_MuxAlt4); + /* Affects PORTA_PCR17 register */ + PORT_SetPinMux(PORTA, 17u, kPORT_MuxAlt4); + /* Affects PORTA_PCR15 register */ + PORT_SetPinMux(PORTA, 15u, kPORT_MuxAlt4); + /* Affects PORTA_PCR28 register */ + PORT_SetPinMux(PORTA, 28u, kPORT_MuxAlt4); + + /* Select the Ethernet timestamp clock source */ + CLOCK_SetEnetTime0Clock(0x2); +} + +/******************************************************************************* + * EOF + ******************************************************************************/ + + diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c b/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c new file mode 100644 index 0000000..d891fb3 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_port.h" +#include "fsl_sysmpu.h" + +/* Initialize the region 1, master 0, 1, 2, 3 - core access rights supervisior r/w/x , user r/w/x. */ +sysmpu_rwxrights_master_access_control_t right = +{ + kSYSMPU_SupervisorEqualToUsermode, + kSYSMPU_UserReadWriteExecute, +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + false, +#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ +}; + +/******************************************************************************* + * Code + ******************************************************************************/ +void kinetis_init_eth_hardware(void) +{ + port_pin_config_t configENET = {0}; + sysmpu_region_config_t regConfig; + sysmpu_config_t config; + + memset(®Config, 0, sizeof(sysmpu_region_config_t)); + memset(&config, 0, sizeof(sysmpu_config_t)); + + regConfig.regionNum = 1; + regConfig.startAddress = 0U; + regConfig.endAddress = 0xFFFFFFFFU; + regConfig.accessRights1[0] = right; + regConfig.accessRights1[1] = right; + regConfig.accessRights1[2] = right; + regConfig.accessRights1[3] = right; + +#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER + regConfig.processIdentifier = 1U; + regConfig.processIdMask = 0U; +#endif + + config.regionConfig = regConfig; + SYSMPU_Init(SYSMPU, &config); + + /* Ungate the port clock */ + CLOCK_EnableClock(kCLOCK_PortA); + CLOCK_EnableClock(kCLOCK_PortB); + CLOCK_EnableClock(kCLOCK_PortE); + + /* Affects PORTE_PCR26 register, configured as ENET_1588 CLKIN */ + PORT_SetPinMux(PORTE, 26u, kPORT_MuxAlt2); + /* Affects PORTB_PCR1 register */ + PORT_SetPinMux(PORTB, 1u, kPORT_MuxAlt4); + + configENET.openDrainEnable = kPORT_OpenDrainEnable; + configENET.mux = kPORT_MuxAlt4; + configENET.pullSelect = kPORT_PullUp; + /* Affects PORTB_PCR0 register */ + PORT_SetPinConfig(PORTB, 0u, &configENET); + + /* Affects PORTA_PCR13 register */ + PORT_SetPinMux(PORTA, 13u, kPORT_MuxAlt4); + /* Affects PORTA_PCR12 register */ + PORT_SetPinMux(PORTA, 12u, kPORT_MuxAlt4); + /* Affects PORTA_PCR14 register */ + PORT_SetPinMux(PORTA, 14u, kPORT_MuxAlt4); + /* Affects PORTA_PCR5 register */ + PORT_SetPinMux(PORTA, 5u, kPORT_MuxAlt4); + /* Affects PORTA_PCR16 register */ + PORT_SetPinMux(PORTA, 16u, kPORT_MuxAlt4); + /* Affects PORTA_PCR17 register */ + PORT_SetPinMux(PORTA, 17u, kPORT_MuxAlt4); + /* Affects PORTA_PCR15 register */ + PORT_SetPinMux(PORTA, 15u, kPORT_MuxAlt4); + + /* Set RMII clock src. */ + CLOCK_SetRmii0Clock(1U); + + /* Select the Ethernet timestamp clock source */ + CLOCK_SetEnetTime0Clock(0x2); +} + +/******************************************************************************* + * EOF + ******************************************************************************/ + + diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.cpp b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.cpp new file mode 100644 index 0000000..7485284 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.cpp @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * Copyright (c) 2017 ARM Limited + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +#include "fsl_phy.h" + +#include "kinetis_emac_config.h" +#include "kinetis_emac.h" +#include "mbed_power_mgmt.h" + +using namespace std::chrono; + +enet_handle_t g_handle; +// TX Buffer descriptors +uint8_t *tx_desc_start_addr; +// RX Buffer descriptors +uint8_t *rx_desc_start_addr; +// RX packet buffer pointers +emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; +// TX packet buffer pointers +emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; +// RX packet payload pointers +uint32_t *rx_ptr[ENET_RX_RING_LEN]; + +/******************************************************************************** + * Internal data + ********************************************************************************/ +#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) +#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) + +extern "C" void kinetis_init_eth_hardware(void); + +/* \brief Flags for worker thread */ +#define FLAG_TX 1 +#define FLAG_RX 2 + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityNormal) + +#define PHY_TASK_PERIOD 200ms + +Kinetis_EMAC::Kinetis_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} +/******************************************************************************** + * Buffer management + ********************************************************************************/ +/* + * This function will queue a new receive buffer + */ +static void update_read_buffer(uint8_t *buf) +{ + if (buf != NULL) { + g_handle.rxBdCurrent->buffer = buf; + } + + /* Clears status. */ + g_handle.rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; + + /* Sets the receive buffer descriptor with the empty flag. */ + g_handle.rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + + /* Increases the buffer descriptor to the next one. */ + if (g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) { + g_handle.rxBdCurrent = g_handle.rxBdBase; + } else { + g_handle.rxBdCurrent++; + } + + /* Actives the receive buffer descriptor. */ + ENET->RDAR = ENET_RDAR_RDAR_MASK; +} + +/** \brief Free TX buffers that are complete + */ +void Kinetis_EMAC::tx_reclaim() +{ + /* Get exclusive access */ + TXLockMutex.lock(); + + // Traverse all descriptors, looking for the ones modified by the uDMA + while ((tx_consume_index != tx_produce_index) && + (!(g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { + memory_manager->free(tx_buff[tx_consume_index % ENET_TX_RING_LEN]); + if (g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { + g_handle.txBdDirty = g_handle.txBdBase; + } else { + g_handle.txBdDirty++; + } + + tx_consume_index += 1; + xTXDCountSem.release(); + } + + /* Restore access */ + TXLockMutex.unlock(); +} + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt. + */ +void Kinetis_EMAC::rx_isr() +{ + if (thread) { + osThreadFlagsSet(thread, FLAG_RX); + } +} + +void Kinetis_EMAC::tx_isr() +{ + osThreadFlagsSet(thread, FLAG_TX); +} + +void Kinetis_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) +{ + Kinetis_EMAC *enet = static_cast(param); + switch (event) { + case kENET_RxEvent: + enet->rx_isr(); + break; + case kENET_TxEvent: + enet->tx_isr(); + break; + default: + break; + } +} + + +/** \brief Low level init of the MAC and PHY. + */ +bool Kinetis_EMAC::low_level_init_successful() +{ + uint8_t i; + uint32_t sysClock; + phy_speed_t phy_speed; + phy_duplex_t phy_duplex; + uint32_t phyAddr = 0; + enet_config_t config; + + // Allocate RX descriptors + rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); + if (!rx_desc_start_addr) { + return false; + } + + // Allocate TX descriptors + tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT); + if (!tx_desc_start_addr) { + return false; + } + + rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT); + tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT); + + /* Create buffers for each receive BD */ + for (i = 0; i < ENET_RX_RING_LEN; i++) { + rx_buff[i] = memory_manager->alloc_heap(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); + if (NULL == rx_buff[i]) { + return false; + } + + rx_ptr[i] = (uint32_t *)memory_manager->get_ptr(rx_buff[i]); + } + + tx_consume_index = tx_produce_index = 0; + + /* prepare the buffer configuration. */ + enet_buffer_config_t buffCfg = { + ENET_RX_RING_LEN, + ENET_TX_RING_LEN, + ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), + 0, + (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, + (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, + (uint8_t *) &rx_ptr, + NULL, + }; + + kinetis_init_eth_hardware(); + + sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); + + ENET_GetDefaultConfig(&config); + + if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) { + return false; + } + + /* Get link information from PHY */ + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); + /* Change the MII speed and duplex for actual link status. */ + config.miiSpeed = (enet_mii_speed_t)phy_speed; + config.miiDuplex = (enet_mii_duplex_t)phy_duplex; + config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; + config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; + config.macSpecialConfig = kENET_ControlFlowControlEnable; + config.txAccelerConfig = 0; + config.rxAccelerConfig = kENET_RxAccelMacCheckEnabled; + ENET_Init(ENET, &g_handle, &config, &buffCfg, hwaddr, sysClock); + + ENET_SetCallback(&g_handle, &Kinetis_EMAC::ethernet_callback, this); + ENET_ActiveRead(ENET); + + return true; +} + +/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. + * + * \param[in] idx index of packet to be read + * \return a emac_mem_buf_t filled with the received packet (including MAC header) + */ +emac_mem_buf_t *Kinetis_EMAC::low_level_input(int idx) +{ + volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent; + emac_mem_buf_t *p = NULL; + emac_mem_buf_t *temp_rxbuf = NULL; + uint32_t length = 0; + const uint16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | + ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; + +#ifdef LOCK_RX_THREAD + /* Get exclusive access */ + TXLockMutex.lock(); +#endif + + /* Determine if a frame has been received */ + if ((bdPtr->control & err_mask) != 0) { + /* Re-use the same buffer in case of error */ + update_read_buffer(NULL); + } else { + /* A packet is waiting, get length */ + length = bdPtr->length; + + /* Zero-copy */ + p = rx_buff[idx]; + memory_manager->set_len(p, length); + + /* Attempt to queue new buffer */ + temp_rxbuf = memory_manager->alloc_heap(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); + if (NULL == temp_rxbuf) { + /* Re-queue the same buffer */ + update_read_buffer(NULL); + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + + return NULL; + } + + rx_buff[idx] = temp_rxbuf; + rx_ptr[idx] = (uint32_t *)memory_manager->get_ptr(rx_buff[idx]); + + update_read_buffer((uint8_t *)rx_ptr[idx]); + } + +#ifdef LOCK_RX_THREAD + osMutexRelease(TXLockMutex); +#endif + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + * \param[in] idx index of packet to be read + */ +void Kinetis_EMAC::input(int idx) +{ + emac_mem_buf_t *p; + + /* move received packet into a new buf */ + p = low_level_input(idx); + if (p == NULL) { + return; + } + + emac_link_input_cb(p); +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void Kinetis_EMAC::thread_function(void *pvParameters) +{ + struct Kinetis_EMAC *kinetis_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); + + MBED_ASSERT(!(flags & osFlagsError)); + + if (flags & FLAG_RX) { + kinetis_enet->packet_rx(); + } + + if (flags & FLAG_TX) { + kinetis_enet->packet_tx(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + */ +void Kinetis_EMAC::packet_rx() +{ + static int idx = 0; + + while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { + input(idx); + idx = (idx + 1) % ENET_RX_RING_LEN; + } +} + +/** \brief Transmit cleanup task + * + * This task is called when a transmit interrupt occurs and + * reclaims the buffer and descriptor used for the packet once + * the packet has been transferred. + */ +void Kinetis_EMAC::packet_tx() +{ + tx_reclaim(); +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf) +{ + // If buffer is chained or not aligned then make a contiguous aligned copy of it + if (memory_manager->get_next(buf) || + reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + memory_manager->free(buf); + return false; + } + + // Copy to new buffer and free original + memory_manager->copy(copy_buf, buf); + memory_manager->free(buf); + buf = copy_buf; + } + + /* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */ + if (!xTXDCountSem.try_acquire_for(10)) { + memory_manager->free(buf); + return false; + } + + /* Get exclusive access */ + TXLockMutex.lock(); + + /* Save the buffer so that it can be freed when transmit is done */ + tx_buff[tx_produce_index % ENET_TX_RING_LEN] = buf; + tx_produce_index += 1; + + /* Setup transfers */ + g_handle.txBdCurrent->buffer = static_cast(memory_manager->get_ptr(buf)); + g_handle.txBdCurrent->length = memory_manager->get_len(buf); + g_handle.txBdCurrent->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); + + /* Increase the buffer descriptor address. */ + if (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { + g_handle.txBdCurrent = g_handle.txBdBase; + } else { + g_handle.txBdCurrent++; + } + + /* Active the transmit buffer descriptor. */ + ENET->TDAR = ENET_TDAR_TDAR_MASK; + + /* Restore access */ + TXLockMutex.unlock(); + + return true; +} + +/******************************************************************************* + * PHY task: monitor link +*******************************************************************************/ + +#define STATE_UNKNOWN (-1) +#define STATE_LINK_DOWN (0) +#define STATE_LINK_UP (1) + +void Kinetis_EMAC::phy_task() +{ + uint32_t phyAddr = 0; + + // Get current status + PHY_STATE crt_state; + bool connection_status; + PHY_GetLinkStatus(ENET, phyAddr, &connection_status); + + if (connection_status) { + crt_state.connected = STATE_LINK_UP; + } else { + crt_state.connected = STATE_LINK_DOWN; + } + + if (crt_state.connected == STATE_LINK_UP) { + if (prev_state.connected != STATE_LINK_UP) { + PHY_AutoNegotiation(ENET, phyAddr); + } + + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); + + if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) { + /* Poke the registers*/ + ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex); + } + } + + // Compare with previous state + if (crt_state.connected != prev_state.connected && emac_link_state_cb) { + emac_link_state_cb(crt_state.connected); + } + + prev_state = crt_state; +} + +bool Kinetis_EMAC::power_up() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + // Can't enter deep sleep as long as Ethernet is active + sleep_manager_lock_deep_sleep(); + + /* Worker thread */ + thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); + + /* Trigger thread to deal with any RX packets that arrived before thread was started */ + rx_isr(); + + /* PHY monitoring task */ + prev_state.connected = STATE_LINK_DOWN; + prev_state.speed = (phy_speed_t)STATE_UNKNOWN; + prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; + + mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &Kinetis_EMAC::phy_task)); + + return true; +} + +uint32_t Kinetis_EMAC::get_mtu_size() const +{ + return KINETIS_ETH_MTU_SIZE; +} + +uint32_t Kinetis_EMAC::get_align_preference() const +{ + return ENET_BUFF_ALIGNMENT; +} + +void Kinetis_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, KINETIS_ETH_IF_NAME, (size < sizeof(KINETIS_ETH_IF_NAME)) ? size : sizeof(KINETIS_ETH_IF_NAME)); +} + +uint8_t Kinetis_EMAC::get_hwaddr_size() const +{ + return KINETIS_HWADDR_SIZE; +} + +bool Kinetis_EMAC::get_hwaddr(uint8_t *addr) const +{ + return false; +} + +void Kinetis_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, sizeof hwaddr); + ENET_SetMacAddr(ENET, const_cast(addr)); +} + +void Kinetis_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void Kinetis_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void Kinetis_EMAC::add_multicast_group(const uint8_t *addr) +{ + ENET_AddMulticastGroup(ENET, const_cast(addr)); +} + +void Kinetis_EMAC::remove_multicast_group(const uint8_t *addr) +{ + // ENET HAL doesn't reference count - ENET_LeaveMulticastGroup just maps + // address to filter bit, and clears that bit, even if shared by other + // addresses. So don't attempt anything for now. +} + +void Kinetis_EMAC::set_all_multicast(bool all) +{ + if (all) { + ENET->GAUR = 0xFFFFFFFFu; + ENET->GALR = 0xFFFFFFFFu; + } +} + +void Kinetis_EMAC::power_down() +{ + // Ethernet went down, can enter deep sleep + sleep_manager_unlock_deep_sleep(); +} + +void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +Kinetis_EMAC &Kinetis_EMAC::get_instance() +{ + static Kinetis_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return Kinetis_EMAC::get_instance(); +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ + diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.h b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.h new file mode 100644 index 0000000..82b588b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KINETIS_EMAC_H_ +#define KINETIS_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class Kinetis_EMAC : public EMAC { +public: + Kinetis_EMAC(); + + static Kinetis_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + bool low_level_init_successful(); + void rx_isr(); + void tx_isr(); + void packet_rx(); + void packet_tx(); + void tx_reclaim(); + void input(int idx); + emac_mem_buf_t *low_level_input(int idx); + static void thread_function(void* pvParameters); + void phy_task(); + static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param); + + mbed_rtos_storage_thread_t thread_cb; + osThreadId_t thread; /**< Processing thread */ + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ + uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + int phy_task_handle; /**< Handle for phy task event */ + struct PHY_STATE { + int connected; + phy_speed_t speed; + phy_duplex_t duplex; + }; + PHY_STATE prev_state; + uint8_t hwaddr[KINETIS_HWADDR_SIZE]; +}; + +#endif /* KINETIS_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac_config.h b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac_config.h new file mode 100644 index 0000000..a56fe41 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/kinetis_emac_config.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef KINETIS_EMAC_CONFIG_H__ +#define KINETIS_EMAC_CONFIG_H__ + +#include "fsl_enet.h" + +#define ENET_RX_RING_LEN MBED_CONF_KINETIS_EMAC_RX_RING_LEN +#define ENET_TX_RING_LEN MBED_CONF_KINETIS_EMAC_TX_RING_LEN + +#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame + +#define KINETIS_HWADDR_SIZE (6) + +#define KINETIS_ETH_MTU_SIZE 1500 +#define KINETIS_ETH_IF_NAME "en" + +#define THREAD_STACKSIZE 512 + +#endif // #define KINETIS_EMAC_CONFIG_H__ + diff --git a/connectivity/drivers/emac/TARGET_Freescale_EMAC/mbed_lib.json b/connectivity/drivers/emac/TARGET_Freescale_EMAC/mbed_lib.json new file mode 100644 index 0000000..102de42 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Freescale_EMAC/mbed_lib.json @@ -0,0 +1,7 @@ +{ + "name": "kinetis-emac", + "config": { + "rx-ring-len": 2, + "tx-ring-len": 1 + } +} diff --git a/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c b/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c new file mode 100644 index 0000000..4c25fab --- /dev/null +++ b/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c @@ -0,0 +1,79 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 GigaDevice Semiconductor Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gd32f30x.h" + +/** + * Initializes the HW pin for enet + * + */ +void enet_bsp_init(void) +{ + /* Enable GPIOs clocks */ + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + rcu_periph_clock_enable(RCU_AF); + + gpio_para_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8); + rcu_pll2_config(RCU_PLL2_MUL10); + rcu_osci_on(RCU_PLL2_CK); + rcu_osci_stab_wait(RCU_PLL2_CK); + rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2); + gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_TX_EN --------------------> PB11 + RMII_MII_TXD0 ---------------------> PB12 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* PA1: ETH_RMII_REF_CLK */ + gpio_para_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_1); + /* PA2: ETH_MDIO */ + gpio_para_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2); + /* PA7: ETH_RMII_CRS_DV */ + gpio_para_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_7); + + /* PB11: ETH_RMII_TX_EN */ + gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); + /* PB12: ETH_RMII_TXD0 */ + gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); + /* PB13: ETH_RMII_TXD1 */ + gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); + + /* PC1: ETH_MDC */ + gpio_para_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1); + /* PC4: ETH_RMII_RXD0 */ + gpio_para_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_4); + /* PC5: ETH_RMII_RXD1 */ + gpio_para_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_5); + + /* Enable the Ethernet global Interrupt */ + nvic_irq_enable(ENET_IRQn, 0x7, 0); + + /* Enable ETHERNET clock */ + rcu_periph_clock_enable(RCU_ENET); + rcu_periph_clock_enable(RCU_ENETTX); + rcu_periph_clock_enable(RCU_ENETRX); +} diff --git a/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c b/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c new file mode 100644 index 0000000..1de087f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c @@ -0,0 +1,102 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 GigaDevice Semiconductor Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gd32f4xx.h" + +/** + * Initializes the HW pin for enet + * + */ +void enet_bsp_init(void) +{ + /* enable GPIOs clocks */ + rcu_periph_clock_enable(RCU_GPIOA); + rcu_periph_clock_enable(RCU_GPIOB); + rcu_periph_clock_enable(RCU_GPIOC); + + /* enable SYSCFG clock */ + rcu_periph_clock_enable(RCU_SYSCFG); + syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_TX_EN --------------------> PB11 + RMII_MII_TXD0 ---------------------> PB12 + RMII_MII_TXD1 ---------------------> PB13 + */ + + /* PA1: ETH_RMII_REF_CLK */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_1); + + /* PA2: ETH_MDIO */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_2); + + /* PA7: ETH_RMII_CRS_DV */ + gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7); + gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_7); + + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2); + gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7); + + /* PB11: ETH_RMII_TX_EN */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_11); + + /* PB12: ETH_RMII_TXD0 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_12); + + /* PB13: ETH_RMII_TXD1 */ + gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13); + gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_13); + + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12); + gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13); + + /* PC1: ETH_MDC */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_1); + + /* PC4: ETH_RMII_RXD0 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_4); + + /* PC5: ETH_RMII_RXD1 */ + gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5); + gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_5); + + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4); + gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5); + + /* enable the ETHERNET global interrupt */ + nvic_irq_enable(ENET_IRQn, 0x7, 0); + + /* enable ETHERNET clock */ + rcu_periph_clock_enable(RCU_ENET); + rcu_periph_clock_enable(RCU_ENETTX); + rcu_periph_clock_enable(RCU_ENETRX); +} diff --git a/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.cpp b/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.cpp new file mode 100644 index 0000000..f08c041 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.cpp @@ -0,0 +1,507 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 GigaDevice Semiconductor Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "mbed_shared_queues.h" +#include "netsocket/nsapi_types.h" + +#include "gd32xx_emac.h" + +using namespace std::chrono; + +/* \brief Flags for worker thread */ +#define _ENET_FLAG_RX (1) + +/** \brief Driver thread priority */ +#define _THREAD_STACKSIZE (512) +#define _THREAD_PRIORITY (osPriorityHigh) + +#define _PHY_TASK_PERIOD (200ms) + +#define _ENET_HW_ADDR_SIZE (6) +#define _ENET_MTU_SIZE (1500) +#define _ENET_IF_NAME "gd" + +#define _ENET_BOARD_PHY_ADDRESS (0x01) +#define _ENET_HARDWARE_CHECKSUM (0) + +#define _GD_MAC_ADDR0 0x02 +#define _GD_MAC_ADDR1 0xaa +#define _GD_MAC_ADDR2 0xbb +#define _GD32_ID_ADDR 0x1FFFF7E8 +/* ENET RxDMA/TxDMA descriptor */ +extern enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM]; +/* ENET receive buffer */ +extern uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; +/* ENET transmit buffer */ +extern uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; +/*global transmit and receive descriptors pointers */ +extern enet_descriptors_struct *dma_current_txdesc; +extern enet_descriptors_struct *dma_current_rxdesc; + +#ifdef __cplusplus +extern "C" { +#endif + +void ENET_IRQHandler(void); +void enet_bsp_init(void); +#ifdef __cplusplus +} +#endif + +/** + * Ethernet IRQ Handler + * + */ +void ENET_IRQHandler(void) +{ + /* frame received */ + if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RS)) { + /* clear the enet DMA Rx interrupt pending bits */ + enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR); + enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_NI_CLR); + /* Ethernet Rx Transfer completed callback */ + GD32_EMAC &emac = GD32_EMAC::get_instance(); + if (emac.rx_thread) { + osThreadFlagsSet(emac.rx_thread, _ENET_FLAG_RX); + } + } +} + +GD32_EMAC::GD32_EMAC() + : rx_thread(0), + phy_status(0) +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} + +/** \brief Low level init of the MAC and PHY. + * + */ +bool GD32_EMAC::low_level_init() +{ + /* Init ETH */ + uint8_t macaddr[6]; + uint32_t i; + +#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) + MACAddr[0] = MBED_MAC_ADDR_0; + MACAddr[1] = MBED_MAC_ADDR_1; + MACAddr[2] = MBED_MAC_ADDR_2; + MACAddr[3] = MBED_MAC_ADDR_3; + MACAddr[4] = MBED_MAC_ADDR_4; + MACAddr[5] = MBED_MAC_ADDR_5; +#else + mbed_mac_address((char *)macaddr); +#endif + + enet_bsp_init(); + /* reset ethernet on AHB bus */ + enet_deinit(); + + if (ERROR == enet_software_reset()) { + while (1); + } + +#if (1 == _ENET_HARDWARE_CHECKSUM) + if (ERROR == enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS)) { + while (1); + } +#else + if (ERROR == enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS)) { + while (1); + } +#endif + /* initialize MAC address in ethernet MAC */ + enet_mac_address_set(ENET_MAC_ADDRESS0, macaddr); + + enet_interrupt_enable(ENET_DMA_INT_NIE); + enet_interrupt_enable(ENET_DMA_INT_RIE); + + /* Initialize Tx Descriptors list: Chain Mode */ + enet_descriptors_chain_init(ENET_DMA_TX); + +#if (1 == _ENET_HARDWARE_CHECKSUM) + /* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ + for (i = 0; i < ENET_TXBUF_NUM; i++) { + enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL); + } +#endif + + /* Initialize Rx Descriptors list: Chain Mode */ + enet_descriptors_chain_init(ENET_DMA_RX); + + /* enable ethernet Rx interrrupt */ + for (i = 0; i < ENET_RXBUF_NUM; i++) { + enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]); + } + + /* enable MAC and DMA transmission and reception */ + enet_enable(); + + return true; +} + +/** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ +bool GD32_EMAC::link_out(emac_mem_buf_t *buf) +{ + emac_mem_buf_t *q; + uint8_t *buffer; + uint16_t framelength = 0; + + /* Get exclusive access */ + TXLockMutex.lock(); + + while ((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) {} + + /* copy frame from pbufs to driver buffers */ + buffer = reinterpret_cast(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR)); + + for (q = buf; q != NULL; q = memory_manager->get_next(q)) { + memcpy(static_cast(&buffer[framelength]), static_cast(memory_manager->get_ptr(q)), memory_manager->get_len(q)); + framelength = framelength + memory_manager->get_len(q); + } + + /* Prepare transmit descriptors to give to DMA */ + if (SUCCESS != ENET_NOCOPY_FRAME_TRANSMIT(framelength)) { + while (1); + } + + memory_manager->free(buf); + /* Restore access */ + TXLockMutex.unlock(); + + return true; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +emac_mem_buf_t *GD32_EMAC::low_level_input(void) +{ + emac_mem_buf_t *p = NULL, *q; + uint32_t l = 0; + uint16_t len; + uint8_t *buffer; + + /* obtain the size of the packet and put it into the "len" variable. */ + len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH); + buffer = reinterpret_cast(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR)); + + if (len > 0) { + /* Allocate a memory buffer chain from buffer pool */ + p = memory_manager->alloc_pool(len, 0); + } else { + return p; + } + + if (p != NULL) { + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + memcpy(static_cast(memory_manager->get_ptr(q)), static_cast(&buffer[l]), memory_manager->get_len(q)); + l = l + memory_manager->get_len(q); + } + } + ENET_NOCOPY_FRAME_RECEIVE(); + + return p; +} + + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +void GD32_EMAC::packet_rx() +{ + /* move received packet into a new buf */ + while (1) { + emac_mem_buf_t *p = NULL; + p = low_level_input(); + + if (p) { + emac_link_input_cb(p); + } else { + break; + } + } +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void GD32_EMAC::thread_function(void *pvParameters) +{ + static struct GD32_EMAC *gd32_enet = static_cast(pvParameters); + + while (1) { + uint32_t flags = osThreadFlagsWait(_ENET_FLAG_RX, osFlagsWaitAny, osWaitForever); + + if (flags & _ENET_FLAG_RX) { + gd32_enet->packet_rx(); + } + } +} + +/** + * This task checks phy link status and updates net status + */ +void GD32_EMAC::phy_task() +{ + uint16_t regval; + + enet_phy_write_read(ENET_PHY_READ, _ENET_BOARD_PHY_ADDRESS, PHY_REG_BSR, ®val); + if (emac_link_state_cb) { + regval &= PHY_LINKED_STATUS; + + if (phy_status != regval) { + if (regval == PHY_LINKED_STATUS) { + emac_link_state_cb(true);; + } else { + emac_link_state_cb(false); + } + } + } + + phy_status = regval; +} + +void GD32_EMAC::eth_arch_enable_interrupts(void) +{ + nvic_irq_enable(ENET_IRQn, 7, 0); +} + +void GD32_EMAC::eth_arch_disable_interrupts(void) +{ + nvic_irq_disable(ENET_IRQn); +} + +/** This returns a unique 6-byte MAC address, based on the device UID +* This function overrides hal/common/mbed_interface.c function +* @param mac A 6-byte array to write the MAC address +*/ +void mbed_mac_address(char *mac) +{ + uint32_t unique_id; + + unique_id = *(uint32_t *)_GD32_ID_ADDR; + mac[0] = _GD_MAC_ADDR0; + mac[1] = _GD_MAC_ADDR1; + mac[2] = _GD_MAC_ADDR2; + mac[3] = (unique_id & 0x00ff0000) >> 16; + mac[4] = (unique_id & 0x0000ff00) >> 8; + mac[5] = (unique_id & 0x000000ff); +} + +/** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ +bool GD32_EMAC::power_up() +{ + /* Initialize the hardware */ + if (true != low_level_init()) { + return false; + } + + /* Worker thread */ + rx_thread = create_new_thread("gd32_emac_thread", &GD32_EMAC::thread_function, this, _THREAD_STACKSIZE, _THREAD_PRIORITY, &rx_thread_cb); + + phy_task_handle = mbed::mbed_event_queue()->call_every(_PHY_TASK_PERIOD, mbed::callback(this, &GD32_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + eth_arch_enable_interrupts(); + + return true; +} + +/** + * Return maximum transmission unit + * + * @return MTU in bytes + */ +uint32_t GD32_EMAC::get_mtu_size() const +{ + return _ENET_MTU_SIZE; +} + +/** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ +uint32_t GD32_EMAC::get_align_preference() const +{ + return 0; +} + +/** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ +void GD32_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, _ENET_IF_NAME, (size < sizeof(_ENET_IF_NAME)) ? size : sizeof(_ENET_IF_NAME)); +} + +/** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ +uint8_t GD32_EMAC::get_hwaddr_size() const +{ + return _ENET_HW_ADDR_SIZE; +} + +/** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ +bool GD32_EMAC::get_hwaddr(uint8_t *addr) const +{ + mbed_mac_address((char *)addr); + return true; +} + +/** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ +void GD32_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +/** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ +void GD32_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +/** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ +void GD32_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +/** Add device to a multicast group + * + * @param address A multicast group hardware address + */ +void GD32_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +/** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ +void GD32_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +/** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ +void GD32_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +/** + * Deinitializes the HW + * + */ +void GD32_EMAC::power_down() +{ + /* No-op at this stage */ +} + +/** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ +void GD32_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +GD32_EMAC &GD32_EMAC::get_instance() +{ + static GD32_EMAC emac; + return emac; +} + +/* Weak so a module can override */ +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return GD32_EMAC::get_instance(); +} diff --git a/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.h b/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.h new file mode 100644 index 0000000..0284c99 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_GD_EMAC/gd32xx_emac.h @@ -0,0 +1,175 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 GigaDevice Semiconductor Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GD32_EMAC_H_ +#define GD32_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Mutex.h" + +class GD32_EMAC : public EMAC { +public: + GD32_EMAC(); + + static GD32_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + /* Called from driver functions */ + osThreadId_t rx_thread; /**< Processing rx thread */ + +private: + bool low_level_init(); + void packet_rx(); + emac_mem_buf_t *low_level_input(void); + static void thread_function(void *pvParameters); + void phy_task(); + void eth_arch_enable_interrupts(); + void eth_arch_disable_interrupts(); + + mbed_rtos_storage_thread_t rx_thread_cb; + + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + + uint32_t phy_status; + int phy_task_handle; /**< Handle for phy task event */ +}; + +#endif /* GD32_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c new file mode 100644 index 0000000..dc8dfea --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c @@ -0,0 +1,496 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: M480 MAC driver source file + */ +#include +#include "m480_eth.h" +#include "mbed_toolchain.h" +//#define NU_TRACE +#include "numaker_eth_hal.h" + +#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) +#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) +#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) +#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0) +#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) +#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0) + +#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel)) +#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel)) + +MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; +MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; + +struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; + +__attribute__((section("EMAC_RAM"))) +MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; +__attribute__((section("EMAC_RAM"))) +MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; + +eth_callback_t nu_eth_txrx_cb = NULL; +void *nu_userData = NULL; + +extern void ack_emac_rx_isr(void); + +static bool isPhyReset = false; +static uint16_t phyLPAval = 0; + +// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns +// Assume we want to set each tick to 100ns. +// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 +// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz +// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 + + + +static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) +{ + + EMAC->MIIMDAT = val; + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; + + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + +} + + +static uint16_t mdio_read(uint8_t addr, uint8_t reg) +{ + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + + return (EMAC->MIIMDAT); +} + +static int reset_phy(void) +{ + + uint16_t reg; + uint32_t delayCnt; + + + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); + + delayCnt = 2000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) { + break; + } + + } + + if (delayCnt == 0) { + NU_DEBUGF(("Reset phy failed\n")); + return (-1); + } + + mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | + ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL); + + reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); + + delayCnt = 200000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) + == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) { + break; + } + } + + if (delayCnt == 0) { + NU_DEBUGF(("AN failed. Set to 100 FULL\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + return (-1); + } else { + reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); + phyLPAval = reg; + + if (reg & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } else if (reg & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; + } else if (reg & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; + } else { + NU_DEBUGF(("10 half\n")); + EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } + } + printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)); + printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)); + + return (0); +} + + +static void init_tx_desc(void) +{ + uint32_t i; + + + cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; + + for (i = 0; i < TX_DESCRIPTOR_NUM; i++) { + tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; + tx_desc[i].buf = &tx_buf[i][0]; + tx_desc[i].status2 = 0; + tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; + + } + EMAC->TXDSA = (unsigned int)&tx_desc[0]; + return; +} + +static void init_rx_desc(void) +{ + uint32_t i; + + + cur_rx_desc_ptr = &rx_desc[0]; + + for (i = 0; i < RX_DESCRIPTOR_NUM; i++) { + rx_desc[i].status1 = OWNERSHIP_EMAC; + rx_desc[i].buf = &rx_buf[i][0]; + rx_desc[i].status2 = 0; + rx_desc[i].next = &rx_desc[(i + 1) % RX_DESCRIPTOR_NUM]; + } + EMAC->RXDSA = (unsigned int)&rx_desc[0]; + return; +} + +void numaker_set_mac_addr(uint8_t *addr) +{ + + EMAC->CAM0M = (addr[0] << 24) | + (addr[1] << 16) | + (addr[2] << 8) | + addr[3]; + + EMAC->CAM0L = (addr[4] << 24) | + (addr[5] << 16); + + +} + +static void __eth_clk_pin_init() +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + + /* Enable IP clock */ + CLK_EnableModuleClock(EMAC_MODULE); + + // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH + CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); + + /* Update System Core Clock */ + SystemCoreClockUpdate(); + + /*---------------------------------------------------------------------------------------------------------*/ + /* Init I/O Multi-function */ + /*---------------------------------------------------------------------------------------------------------*/ + // Configure RMII pins + SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); + SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV; + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); + SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0; + SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; + SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK; + SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk | + SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk); + SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC | + SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO | + SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 | + SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 | + SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN; + + // Enable high slew rate on all RMII TX output pins + PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) | + (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) | + (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos); + + + /* Lock protected registers */ + SYS_LockReg(); + + +} + +void numaker_eth_init(uint8_t *mac_addr) +{ + + // init CLK & pins + __eth_clk_pin_init(); + + // Reset MAC + EMAC->CTL = EMAC_CTL_RST_Msk; + while (EMAC->CTL & EMAC_CTL_RST_Msk) {} + + init_tx_desc(); + init_rx_desc(); + + numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... + + + /* Configure the MAC interrupt enable register. */ + EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk | + EMAC_INTEN_RXGDIEN_Msk | + EMAC_INTEN_TXCPIEN_Msk | + EMAC_INTEN_RXBEIEN_Msk | + EMAC_INTEN_TXBEIEN_Msk | + EMAC_INTEN_RDUIEN_Msk | + EMAC_INTEN_TSALMIEN_Msk | + EMAC_INTEN_WOLIEN_Msk; + + /* Configure the MAC control register. */ + EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk; + + /* Accept packets for us and all broadcast and multicast packets */ + EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | + EMAC_CAMCTL_AMP_Msk | + EMAC_CAMCTL_ABP_Msk; + EMAC->CAMEN = 1; // Enable CAM entry 0 + /* Limit the max receive frame length to 1514 + 4 */ + EMAC->MRFL = NU_ETH_MAX_FLEN; + + /* Set RX FIFO threshold as 8 words */ + EMAC->FIFOCTL = 0x00200100; + + if (isPhyReset != true) { + if (!reset_phy()) { + isPhyReset = true; + } + } else { + if (phyLPAval & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } else if (phyLPAval & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; + } else if (phyLPAval & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; + } else { + NU_DEBUGF(("10 half\n")); + EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } + } + + EMAC_ENABLE_RX(); + EMAC_ENABLE_TX(); + +} + + + +void ETH_halt(void) +{ + + EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); +} + +unsigned int m_status; + +void EMAC_RX_IRQHandler(void) +{ + m_status = EMAC->INTSTS & 0xFFFF; + EMAC->INTSTS = m_status; + if (m_status & EMAC_INTSTS_RXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('B', nu_userData); + } + return; + } + EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('R', nu_userData); + } +} + + +void numaker_eth_trigger_rx(void) +{ + EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + ETH_TRIGGER_RX(); +} + +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) +{ + unsigned int cur_entry, status; + + cur_entry = EMAC->CRXDSA; + if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures + return -1; + } + status = cur_rx_desc_ptr->status1; + + if (status & OWNERSHIP_EMAC) { + return -1; + } + + if (status & RXFD_RXGD) { + *buf = cur_rx_desc_ptr->buf; + *len = status & 0xFFFF; + // length of payload should be <= 1514 + if (*len > (NU_ETH_MAX_FLEN - 4)) { + NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); + *len = 0; // Skip this unexpected long packet + } + if (*len == (NU_ETH_MAX_FLEN - 4)) { + NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); + } + } + return 0; +} + +void numaker_eth_rx_next(void) +{ + cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; + cur_rx_desc_ptr = cur_rx_desc_ptr->next; +} + +void EMAC_TX_IRQHandler(void) +{ + unsigned int cur_entry, status; + + status = EMAC->INTSTS & 0xFFFF0000; + EMAC->INTSTS = status; + if (status & EMAC_INTSTS_TXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + mbed_error_printf("### TX Bus error [0x%x]\r\n", status); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('B', nu_userData); + } + return; + } + + cur_entry = EMAC->CTXDSA; + + while (cur_entry != (uint32_t)fin_tx_desc_ptr) { + + fin_tx_desc_ptr = fin_tx_desc_ptr->next; + } + + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('T', nu_userData); + } +} + +uint8_t *numaker_eth_get_tx_buf(void) +{ + if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) { + return (NULL); + } else { + return (cur_tx_desc_ptr->buf); + } +} + +void numaker_eth_trigger_tx(uint16_t length, void *p) +{ + struct eth_descriptor volatile *desc; + cur_tx_desc_ptr->status2 = (unsigned int)length; + desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr + cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; + cur_tx_desc_ptr = desc; + + ETH_TRIGGER_TX(); + +} + +int numaker_eth_link_ok(void) +{ + /* first, a dummy read to latch */ + mdio_read(CONFIG_PHY_ADDR, MII_BMSR); + if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) { + return 1; + } + return 0; +} + +void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) +{ + nu_eth_txrx_cb = eth_cb; + nu_userData = userData; +} + +// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address +void mbed_mac_address(char *mac) +{ + uint32_t uID1; + // Fetch word 0 + uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 + // Fetch word 1 + // we only want bottom 16 bits of word1 (MAC bits 32-47) + // and bit 9 forced to 1, bit 8 forced to 0 + // Locally administered MAC, reduced conflicts + // http://en.wikipedia.org/wiki/MAC_address + uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 + + if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash + // with a semi-unique MAC address from the UUID + /* Enable FMC ISP function */ + SYS_UnlockReg(); + FMC_Open(); + // = FMC_ReadUID(0); + uID1 = FMC_ReadUID(1); + word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; + word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF); + /* Disable FMC ISP function */ + FMC_Close(); + /* Lock protected registers */ + SYS_LockReg(); + } + + word1 |= 0x00000200; + word1 &= 0x0000FEFF; + + mac[0] = (word1 & 0x0000ff00) >> 8; + mac[1] = (word1 & 0x000000ff); + mac[2] = (word0 & 0xff000000) >> 24; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); +} + +void numaker_eth_enable_interrupts(void) +{ + EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk ; + NVIC_EnableIRQ(EMAC_RX_IRQn); + NVIC_EnableIRQ(EMAC_TX_IRQn); +} + +void numaker_eth_disable_interrupts(void) +{ + NVIC_DisableIRQ(EMAC_RX_IRQn); + NVIC_DisableIRQ(EMAC_TX_IRQn); +} diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h new file mode 100644 index 0000000..9a1be26 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: M480 EMAC driver header file + */ + +#include "numaker_emac_config.h" +#include "M480.h" +#ifndef _M480_ETH_ +#define _M480_ETH_ + +/* Generic MII registers. */ + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ + +/* Basic mode control register. */ +#define BMCR_RESV 0x007f /* Unused... */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ +#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ +#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset the DP83840 */ + +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_RFAULT 0x0010 /* Remote fault detected */ +#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ +#define BMSR_RESV 0x07c0 /* Unused... */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ + +/* Advertisement control register. */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define ADVERTISE_RESV 0x1c00 /* Unused... */ +#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +#define RX_DESCRIPTOR_NUM NU_RX_RING_LEN//4 //2 // 4: Max Number of Rx Frame Descriptors +#define TX_DESCRIPTOR_NUM NU_TX_RING_LEN//4 //2 // 4: Max number of Tx Frame Descriptors + +#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment + +#define CONFIG_PHY_ADDR 1 + + +// Frame Descriptor's Owner bit +#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC +//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU + + + +// Rx Frame Descriptor Status +#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received +#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available + + +// Tx Frame Descriptor's Control bits +#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable +#define TXFD_INTEN 0x04 // Interrupt Enable +#define TXFD_CRCAPP 0x02 // Append CRC +#define TXFD_PADEN 0x01 // Padding Enable + +// Tx Frame Descriptor Status +#define TXFD_TXCP 0x00080000 // Transmission Completion +#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available + +// Tx/Rx buffer descriptor structure +struct eth_descriptor; +struct eth_descriptor { + uint32_t status1; + uint8_t *buf; + uint32_t status2; + struct eth_descriptor *next; +#ifdef TIME_STAMPING + uint32_t backup1; + uint32_t backup2; + uint32_t reserved1; + uint32_t reserved2; +#endif +}; + +#ifdef TIME_STAMPING + +#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) +#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) +s32_t ETH_settime(u32_t sec, u32_t nsec); +s32_t ETH_gettime(u32_t *sec, u32_t *nsec); +s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); +s32_t ETH_adjtimex(int ppm); +void ETH_setinc(void); + +#endif + +#endif /* _M480_ETH_ */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c new file mode 100644 index 0000000..e0f77b7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: NUC472 MAC driver source file + */ +#include +#include "nuc472_eth.h" +#include "mbed_toolchain.h" +//#define NU_TRACE +#include "numaker_eth_hal.h" + +#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) +#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) +#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) +#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0) +#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) +#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0) + +#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel)) +#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel)) + +MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; +MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; + +struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; + +__attribute__((section("EMAC_RAM"))) +MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; +__attribute__((section("EMAC_RAM"))) +MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; + +eth_callback_t nu_eth_txrx_cb = NULL; +void *nu_userData = NULL; + +extern void ack_emac_rx_isr(void); +static bool isPhyReset = false; +static uint16_t phyLPAval = 0; + +// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns +// Assume we want to set each tick to 100ns. +// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 +// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz +// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 + + + +static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) +{ + + EMAC->MIIMDAT = val; + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; + + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + +} + + +static uint16_t mdio_read(uint8_t addr, uint8_t reg) +{ + EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; + while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); + + return (EMAC->MIIMDAT); +} + +static int reset_phy(void) +{ + + uint16_t reg; + uint32_t delayCnt; + + + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); + + delayCnt = 2000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) { + break; + } + + } + + if (delayCnt == 0) { + NU_DEBUGF(("Reset phy failed\n")); + return (-1); + } + + mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | + ADVERTISE_10HALF | + ADVERTISE_10FULL | + ADVERTISE_100HALF | + ADVERTISE_100FULL); + + reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); + mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); + + delayCnt = 200000; + while (delayCnt > 0) { + delayCnt--; + if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) + == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) { + break; + } + } + + if (delayCnt == 0) { + NU_DEBUGF(("AN failed. Set to 100 FULL\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + return (-1); + } else { + reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); + phyLPAval = reg; + + if (reg & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } else if (reg & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; + } else if (reg & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; + } else { + NU_DEBUGF(("10 half\n")); + EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } + } + printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)); + printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)); + + return (0); +} + + +static void init_tx_desc(void) +{ + uint32_t i; + + + cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; + + for (i = 0; i < TX_DESCRIPTOR_NUM; i++) { + tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; + tx_desc[i].buf = &tx_buf[i][0]; + tx_desc[i].status2 = 0; + tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; + + } + EMAC->TXDSA = (unsigned int)&tx_desc[0]; + return; +} + +static void init_rx_desc(void) +{ + uint32_t i; + + + cur_rx_desc_ptr = &rx_desc[0]; + + for (i = 0; i < RX_DESCRIPTOR_NUM; i++) { + rx_desc[i].status1 = OWNERSHIP_EMAC; + rx_desc[i].buf = &rx_buf[i][0]; + rx_desc[i].status2 = 0; + rx_desc[i].next = &rx_desc[(i + 1) % (RX_DESCRIPTOR_NUM)]; + } + EMAC->RXDSA = (unsigned int)&rx_desc[0]; + return; +} + +void numaker_set_mac_addr(uint8_t *addr) +{ + + EMAC->CAM0M = (addr[0] << 24) | + (addr[1] << 16) | + (addr[2] << 8) | + addr[3]; + + EMAC->CAM0L = (addr[4] << 24) | + (addr[5] << 16); + + EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC_CAMCTL_AMP_Msk | EMAC_CAMCTL_ABP_Msk; + EMAC->CAMEN = 1; // Enable CAM entry 0 + +} + +static void __eth_clk_pin_init() +{ + /* Unlock protected registers */ + SYS_UnlockReg(); + /* Enable IP clock */ + CLK_EnableModuleClock(EMAC_MODULE); + // Configure MDC clock rate to HCLK / (127 + 1) = 656 kHz if system is running at 84 MHz + CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); + /* Update System Core Clock */ + SystemCoreClockUpdate(); + /*---------------------------------------------------------------------------------------------------------*/ + /* Init I/O Multi-function */ + /*---------------------------------------------------------------------------------------------------------*/ + // Configure RMII pins + SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk | + SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | + SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); + SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK | + SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR | + SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV | + SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1 | + SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0 | + SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0 | + SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1; + + SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; + SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN; + // Enable high slew rate on all RMII pins + PC->SLEWCTL |= 0x1DF; + + // Configure MDC, MDIO at PB14 & PB15 + SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB14MFP_Msk | SYS_GPB_MFPH_PB15MFP_Msk); + SYS->GPB_MFPH |= SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO; + + /* Lock protected registers */ + SYS_LockReg(); +} + +void numaker_eth_init(uint8_t *mac_addr) +{ + // init CLK & pins + __eth_clk_pin_init(); + + // Reset MAC + EMAC->CTL = EMAC_CTL_RST_Msk; + while (EMAC->CTL & EMAC_CTL_RST_Msk) {} + + init_tx_desc(); + init_rx_desc(); + + numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... + + + EMAC->CTL |= EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk | EMAC_CTL_RMIIEN_Msk | EMAC_CTL_RMIIRXCTL_Msk; + EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_RXGDIEN_Msk | + EMAC_INTEN_RDUIEN_Msk | + EMAC_INTEN_RXBEIEN_Msk | + EMAC_INTEN_TXIEN_Msk | + EMAC_INTEN_TXABTIEN_Msk | + EMAC_INTEN_TXCPIEN_Msk | + EMAC_INTEN_TXBEIEN_Msk; + /* Limit the max receive frame length to 1514 + 4 */ + EMAC->MRFL = NU_ETH_MAX_FLEN; + + /* Set RX FIFO threshold as 8 words */ + + if (isPhyReset != true) { + if (!reset_phy()) { + isPhyReset = true; + } + } else { + if (phyLPAval & ADVERTISE_100FULL) { + NU_DEBUGF(("100 full\n")); + EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } else if (phyLPAval & ADVERTISE_100HALF) { + NU_DEBUGF(("100 half\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; + } else if (phyLPAval & ADVERTISE_10FULL) { + NU_DEBUGF(("10 full\n")); + EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; + } else { + NU_DEBUGF(("10 half\n")); + EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); + } + } + + EMAC_ENABLE_RX(); + EMAC_ENABLE_TX(); + +} + + + +void ETH_halt(void) +{ + + EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); +} + +unsigned int m_status; + +void EMAC_RX_IRQHandler(void) +{ + m_status = EMAC->INTSTS & 0xFFFF; + EMAC->INTSTS = m_status; + if (m_status & EMAC_INTSTS_RXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('B', nu_userData); + } + return; + } + EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('R', nu_userData); + } +} + + +void numaker_eth_trigger_rx(void) +{ + EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); + ETH_TRIGGER_RX(); +} + +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) +{ + unsigned int cur_entry, status; + + cur_entry = EMAC->CRXDSA; + if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures + return -1; + } + status = cur_rx_desc_ptr->status1; + + if (status & OWNERSHIP_EMAC) { + return -1; + } + + if (status & RXFD_RXGD) { + *buf = cur_rx_desc_ptr->buf; + *len = status & 0xFFFF; + // length of payload should be <= 1514 + if (*len > (NU_ETH_MAX_FLEN - 4)) { + NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); + *len = 0; // Skip this unexpected long packet + } + if (*len == (NU_ETH_MAX_FLEN - 4)) { + NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); + } + } + return 0; +} + +void numaker_eth_rx_next(void) +{ + cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; + cur_rx_desc_ptr = cur_rx_desc_ptr->next; +} + +void EMAC_TX_IRQHandler(void) +{ + unsigned int cur_entry, status; + + status = EMAC->INTSTS & 0xFFFF0000; + EMAC->INTSTS = status; + if (status & EMAC_INTSTS_TXBEIF_Msk) { + // Shouldn't goes here, unless descriptor corrupted + mbed_error_printf("### TX Bus error [0x%x]\r\n", status); + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('B', nu_userData); + } + return; + } + + cur_entry = EMAC->CTXDSA; + + while (cur_entry != (uint32_t)fin_tx_desc_ptr) { + + fin_tx_desc_ptr = fin_tx_desc_ptr->next; + } + + if (nu_eth_txrx_cb != NULL) { + nu_eth_txrx_cb('T', nu_userData); + } +} + +uint8_t *numaker_eth_get_tx_buf(void) +{ + if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) { + return (NULL); + } else { + return (cur_tx_desc_ptr->buf); + } +} + +void numaker_eth_trigger_tx(uint16_t length, void *p) +{ + struct eth_descriptor volatile *desc; + cur_tx_desc_ptr->status2 = (unsigned int)length; + desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr + cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; + cur_tx_desc_ptr = desc; + + ETH_TRIGGER_TX(); + +} + +int numaker_eth_link_ok(void) +{ + /* first, a dummy read to latch */ + mdio_read(CONFIG_PHY_ADDR, MII_BMSR); + if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) { + return 1; + } + return 0; +} + +void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) +{ + nu_eth_txrx_cb = eth_cb; + nu_userData = userData; +} + +// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address +void mbed_mac_address(char *mac) +{ + uint32_t uID1; + // Fetch word 0 + uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 + // Fetch word 1 + // we only want bottom 16 bits of word1 (MAC bits 32-47) + // and bit 9 forced to 1, bit 8 forced to 0 + // Locally administered MAC, reduced conflicts + // http://en.wikipedia.org/wiki/MAC_address + uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 + + if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash + // with a semi-unique MAC address from the UUID + /* Enable FMC ISP function */ + SYS_UnlockReg(); + FMC_Open(); + // = FMC_ReadUID(0); + uID1 = FMC_ReadUID(1); + word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; + word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF); + /* Disable FMC ISP function */ + FMC_Close(); + /* Lock protected registers */ + SYS_LockReg(); + } + + word1 |= 0x00000200; + word1 &= 0x0000FEFF; + + mac[0] = (word1 & 0x0000ff00) >> 8; + mac[1] = (word1 & 0x000000ff); + mac[2] = (word0 & 0xff000000) >> 24; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); +} + +void numaker_eth_enable_interrupts(void) +{ + EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | + EMAC_INTEN_TXIEN_Msk ; + NVIC_EnableIRQ(EMAC_RX_IRQn); + NVIC_EnableIRQ(EMAC_TX_IRQn); +} + +void numaker_eth_disable_interrupts(void) +{ + NVIC_DisableIRQ(EMAC_RX_IRQn); + NVIC_DisableIRQ(EMAC_TX_IRQn); +} diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h new file mode 100644 index 0000000..1766b03 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: NUC472 EMAC driver header file + */ +#include "NUC472_442.h" +#include "numaker_emac_config.h" +#ifndef _NUC472_ETH_ +#define _NUC472_ETH_ + +/* Generic MII registers. */ + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define MII_PHYSID1 0x02 /* PHYS ID 1 */ +#define MII_PHYSID2 0x03 /* PHYS ID 2 */ +#define MII_ADVERTISE 0x04 /* Advertisement control reg */ +#define MII_LPA 0x05 /* Link partner ability reg */ +#define MII_EXPANSION 0x06 /* Expansion register */ +#define MII_DCOUNTER 0x12 /* Disconnect counter */ +#define MII_FCSCOUNTER 0x13 /* False carrier counter */ +#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ +#define MII_RERRCOUNTER 0x15 /* Receive error counter */ +#define MII_SREVISION 0x16 /* Silicon revision */ +#define MII_RESV1 0x17 /* Reserved... */ +#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ +#define MII_PHYADDR 0x19 /* PHY address */ +#define MII_RESV2 0x1a /* Reserved... */ +#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ +#define MII_NCONFIG 0x1c /* Network interface config */ + +/* Basic mode control register. */ +#define BMCR_RESV 0x007f /* Unused... */ +#define BMCR_CTST 0x0080 /* Collision test */ +#define BMCR_FULLDPLX 0x0100 /* Full duplex */ +#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ +#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ +#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ +#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ +#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ +#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ +#define BMCR_RESET 0x8000 /* Reset the DP83840 */ + +/* Basic mode status register. */ +#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ +#define BMSR_RFAULT 0x0010 /* Remote fault detected */ +#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ +#define BMSR_RESV 0x07c0 /* Unused... */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ + +/* Advertisement control register. */ +#define ADVERTISE_SLCT 0x001f /* Selector bits */ +#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ +#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ +#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ +#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ +#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ +#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ +#define ADVERTISE_RESV 0x1c00 /* Unused... */ +#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ +#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ +#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ + +#define RX_DESCRIPTOR_NUM NU_RX_RING_LEN//4 //2 // 4: Max Number of Rx Frame Descriptors +#define TX_DESCRIPTOR_NUM NU_TX_RING_LEN//4 //2 // 4: Max number of Tx Frame Descriptors + +#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment + +#define CONFIG_PHY_ADDR 1 + + +// Frame Descriptor's Owner bit +#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC +//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU + + + +// Rx Frame Descriptor Status +#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received +#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available + + +// Tx Frame Descriptor's Control bits +#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable +#define TXFD_INTEN 0x04 // Interrupt Enable +#define TXFD_CRCAPP 0x02 // Append CRC +#define TXFD_PADEN 0x01 // Padding Enable + +// Tx Frame Descriptor Status +#define TXFD_TXCP 0x00080000 // Transmission Completion +#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available + +// Tx/Rx buffer descriptor structure +struct eth_descriptor; +struct eth_descriptor { + uint32_t status1; + uint8_t *buf; + uint32_t status2; + struct eth_descriptor *next; +#ifdef TIME_STAMPING + uint32_t backup1; + uint32_t backup2; + uint32_t reserved1; + uint32_t reserved2; +#endif +}; + +#ifdef TIME_STAMPING + +#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) +#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) +s32_t ETH_settime(u32_t sec, u32_t nsec); +s32_t ETH_gettime(u32_t *sec, u32_t *nsec); +s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); +s32_t ETH_adjtimex(int ppm); +void ETH_setinc(void); + +#endif + +#endif /* _NUC472_ETH_ */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.cpp b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.cpp new file mode 100644 index 0000000..945583e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.cpp @@ -0,0 +1,438 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * Description: NuMaker EMAC + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +//#define NU_TRACE + +#include "numaker_emac_config.h" +#include "numaker_emac.h" +#include "numaker_eth_hal.h" + +using namespace std::chrono; + +/******************************************************************************** + * + ********************************************************************************/ +#define NU_BUFF_ALIGNMENT 4 +#define PHY_LINKED_STATE 1 +#define PHY_UNLINKED_STATE 0 +#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment + +extern "C" void numaker_eth_rx_next(void); +/* \brief Flags for worker thread */ +#define FLAG_TX 1 +#define FLAG_RX 2 +#define FLAG_BUS_RESET 4 + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityNormal) + +#define PHY_TASK_PERIOD 200ms + +NUMAKER_EMAC::NUMAKER_EMAC() : thread(0), hwaddr() +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} + + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt. + */ +void NUMAKER_EMAC::rx_isr() +{ + if (thread) { + osThreadFlagsSet(thread, FLAG_RX); + } +} + +void NUMAKER_EMAC::bus_isr() +{ + if (thread) { + osThreadFlagsSet(thread, FLAG_BUS_RESET); + } +} + +void NUMAKER_EMAC::tx_isr() +{ + /* No-op at this stage */ +} + +void NUMAKER_EMAC::ethernet_callback(char event, void *param) +{ + NUMAKER_EMAC *enet = static_cast(param); + switch (event) { + case 'R': //For RX event + enet->rx_isr(); + break; + case 'T': //For TX event + enet->tx_isr(); + break; + case 'B': // For BUS event + enet->bus_isr(); + default: + break; + } +} + + +/** + * In this function, the hardware should be initialized. + */ +bool NUMAKER_EMAC::low_level_init_successful() +{ + /* Init ETH */ + + mbed_mac_address((char *)hwaddr); + printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); + /* Enable clock & set EMAC configuration */ + /* Enable MAC and DMA transmission and reception */ + numaker_eth_init(hwaddr); + + numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this); + + return true; +} + + +int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf) +{ + uint16_t len = 0; + uint8_t *buffer; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + emac_mem_buf_t *q; + uint32_t payloadoffset = 0; + + /* get received frame */ + if (numaker_eth_get_rx_buf(&len, &buffer) != 0) { + return -1; + } + byteslefttocopy = len; + + if (len > 0) { + /* Allocate a memory buffer chain from buffer pool */ + *buf = memory_manager->alloc_pool(len, 0); + } + NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, len, *buf)); + if (*buf != NULL) { + bufferoffset = 0; + for (q = *buf; q != NULL; q = memory_manager->get_next(q)) { + byteslefttocopy = memory_manager->get_len(q); + payloadoffset = 0; + NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n", bufferoffset, byteslefttocopy)); + /* Copy data in pbuf */ + memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, byteslefttocopy); + + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + return 0; +} + + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ + +void NUMAKER_EMAC::thread_function(void *pvParameters) +{ + static struct NUMAKER_EMAC *nu_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_BUS_RESET, osFlagsWaitAny, osWaitForever); + + if (flags & FLAG_RX) { + nu_enet->packet_rx(); + } + if (flags & FLAG_BUS_RESET) { + NU_DEBUGF(("BUS error and reset bus\r\n")); + nu_enet->bus_reset(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + */ +void NUMAKER_EMAC::packet_rx() +{ + /* move received packet into a new buf */ + while (1) { + emac_mem_buf_t *p = NULL; + if (low_level_input(&p) < 0) { + break; + } + if (p) { + NU_DEBUGF(("%s ... p=0x%x\r\n", __FUNCTION__, p)); + emac_link_input_cb(p); + } + numaker_eth_rx_next(); + } + numaker_eth_trigger_rx(); + +} + + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the buf that is passed to the function. This buf + * might be chained. + * + * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return true if the packet could be sent + * false value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become available since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf) +{ + bool result = false; + emac_mem_buf_t *q; + uint8_t *buffer = NULL; + uint32_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + + /* Get exclusive access */ + TXLockMutex.lock(); + buffer = numaker_eth_get_tx_buf(); + NU_DEBUGF(("%s ... buffer=0x%x\r\n", __FUNCTION__, buffer)); + if (buffer == NULL) { + goto error; + } + /* copy frame from buf to driver buffers */ + for (q = buf; q != NULL; q = memory_manager->get_next(q)) { + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = memory_manager->get_len(q); + payloadoffset = 0; + NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n", bufferoffset, byteslefttocopy)); + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) { + /* Copy data to Tx buffer*/ + memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, (PACKET_BUFFER_SIZE - bufferoffset)); + + /* Point to next descriptor */ + numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL); + buffer = numaker_eth_get_tx_buf(); + if (buffer == NULL) { + goto error; + } + + byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset); + payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset); + framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Prepare transmit descriptors to give to DMA */ + numaker_eth_trigger_tx(framelength, NULL); + + result = true; + +error: + + memory_manager->free(buf); + + /* Restore access */ + TXLockMutex.unlock(); + + return result; +} + + +void NUMAKER_EMAC::phy_task() +{ + + // Get current status + int state; + state = numaker_eth_link_ok(); + + + if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) { + NU_DEBUGF(("Link Up\r\n")); + if (emac_link_state_cb) { + emac_link_state_cb(true); + } + } else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) { + NU_DEBUGF(("Link Down\r\n")); + if (emac_link_state_cb) { + emac_link_state_cb(false); + } + } + phy_state = state; + +} + +bool NUMAKER_EMAC::power_up() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + /* Worker thread */ + thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb); + + /* PHY monitoring task */ + phy_state = PHY_UNLINKED_STATE; + + phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &NUMAKER_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + numaker_eth_enable_interrupts(); + return true; +} + +bool NUMAKER_EMAC::bus_reset() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + numaker_eth_enable_interrupts(); + return true; +} + + +uint32_t NUMAKER_EMAC::get_mtu_size() const +{ + return NU_ETH_MTU_SIZE; +} + +uint32_t NUMAKER_EMAC::get_align_preference() const +{ + return NU_BUFF_ALIGNMENT; +} + +void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME)); +} + +uint8_t NUMAKER_EMAC::get_hwaddr_size() const +{ + return NU_HWADDR_SIZE; +} + +bool NUMAKER_EMAC::get_hwaddr(uint8_t *addr) const +{ + mbed_mac_address((char *)addr); + return true; +} + +void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, sizeof hwaddr); + numaker_set_mac_addr(const_cast(addr)); +} + +void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void NUMAKER_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + + +void NUMAKER_EMAC::power_down() +{ + /* No-op at this stage */ +} + +void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +NUMAKER_EMAC &NUMAKER_EMAC::get_instance() +{ + static NUMAKER_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return NUMAKER_EMAC::get_instance(); +} + + + + diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.h new file mode 100644 index 0000000..c7c4955 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac.h @@ -0,0 +1,173 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NUMAKER_EMAC_H_ +#define NUMAKER_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Mutex.h" + +class NUMAKER_EMAC : public EMAC { +public: + NUMAKER_EMAC(); + + static NUMAKER_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + bool low_level_init_successful(); + void tx_isr(); + void rx_isr(); + void bus_isr(); + void packet_rx(); + bool bus_reset(); + int low_level_input(emac_mem_buf_t **buf); + static void thread_function(void *pvParameters); + void phy_task(); + static void ethernet_callback(char event, void *param); + + mbed_rtos_storage_thread_t thread_cb; + osThreadId_t thread; /**< Processing thread */ + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + int phy_task_handle; /**< Handle for phy task event */ + int phy_state; + uint8_t hwaddr[6]; +}; + +#endif /* NUMAKER_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac_config.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac_config.h new file mode 100644 index 0000000..7bb83c3 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_emac_config.h @@ -0,0 +1,35 @@ +/* Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * + * Description: NuMaker EMAC Config header file + */ + +#ifndef NUMAKER_EMAC_CONFIG_H__ +#define NUMAKER_EMAC_CONFIG_H__ + +#define NU_RX_RING_LEN (8) +#define NU_TX_RING_LEN (4) + +#define NU_ETH_MAX_FLEN (1518) + +#define NU_HWADDR_SIZE (6) + +#define NU_ETH_MTU_SIZE 1500 +#define NU_ETH_IF_NAME "nu" + +#define THREAD_STACKSIZE 512 + +#endif // #define NUMAKER_EMAC_CONFIG_H__ + diff --git a/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_eth_hal.h b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_eth_hal.h new file mode 100644 index 0000000..e84ee60 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NUVOTON_EMAC/numaker_eth_hal.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 Nuvoton Technology Corp. + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Description: NuMaker EMAC HAL header file + */ + +#ifndef NUMAKER_ETH_HAL_ +#define NUMAKER_ETH_HAL_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef NU_TRACE +#define NU_DEBUGF(x) { printf x; } +#else +#define NU_DEBUGF(x) +#endif + +typedef void (* eth_callback_t) (char, void*); +void mbed_mac_address(char *mac); +void numaker_eth_init(uint8_t *mac_addr); +void numaker_eth_trigger_rx(void); +int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf); +uint8_t *numaker_eth_get_tx_buf(void); +void numaker_eth_trigger_tx(uint16_t length, void *p); +int numaker_eth_link_ok(void); +void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData); +void numaker_set_mac_addr(uint8_t *addr); +void numaker_eth_enable_interrupts(void); +void numaker_eth_disable_interrupts(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NUMAKER_ETH_HAL_ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c new file mode 100644 index 0000000..2f6e27f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fsl_gpio.h" +#include "fsl_iomuxc.h" +#include "fsl_clock.h" +#include "mbed_wait_api.h" + +/******************************************************************************* + * Code + ******************************************************************************/ +static void BOARD_InitModuleClock(void) +{ + const clock_enet_pll_config_t config = {true, false, 1}; + CLOCK_InitEnetPll(&config); +} + +void kinetis_init_eth_hardware(void) +{ + gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; + + CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ + + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 is configured as ENET_RX_DATA00 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 is configured as ENET_RX_DATA01 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 is configured as ENET_RX_EN */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 is configured as ENET_TX_DATA00 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 is configured as ENET_TX_DATA01 */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 is configured as ENET_TX_EN */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 is configured as ENET_REF_CLK */ + 1U); /* Software Input On Field: Force input path of pad GPIO_B1_10 */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 is configured as ENET_RX_ER */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 is configured as ENET_MDC */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinMux( + IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 is configured as ENET_MDIO */ + 0U); /* Software Input On Field: Input Path is determined by functionality */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 PAD functional properties : */ + 0xB0A9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 PAD functional properties : */ + 0xB0A9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: medium(100MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 PAD functional properties : */ + 0x31u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/6 + Speed Field: low(50MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Disabled + Pull / Keep Select Field: Keeper + Pull Up / Down Config. Field: 100K Ohm Pull Down + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 PAD functional properties : */ + 0xB0E9u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: max(200MHz) + Open Drain Enable Field: Open Drain Disabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + IOMUXC_SetPinConfig( + IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 PAD functional properties : */ + 0xB829u); /* Slew Rate Field: Fast Slew Rate + Drive Strength Field: R0/5 + Speed Field: low(50MHz) + Open Drain Enable Field: Open Drain Enabled + Pull / Keep Enable Field: Pull/Keeper Enabled + Pull / Keep Select Field: Pull + Pull Up / Down Config. Field: 100K Ohm Pull Up + Hyst. Enable Field: Hysteresis Disabled */ + + + BOARD_InitModuleClock(); + + IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true); + + GPIO_PinInit(GPIO1, 9, &gpio_config); + GPIO_PinInit(GPIO1, 10, &gpio_config); + /* pull up the ENET_INT before RESET. */ + GPIO_WritePinOutput(GPIO1, 10, 1); + GPIO_WritePinOutput(GPIO1, 9, 0); + wait_us(1 * 1000); + GPIO_WritePinOutput(GPIO1, 9, 1); +} + +/******************************************************************************* + * EOF + ******************************************************************************/ + + diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp new file mode 100644 index 0000000..f69d524 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * Copyright (c) 2017 ARM Limited + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +#include "fsl_phy.h" + +#include "imx_emac_config.h" +#include "imx_emac.h" +#include "mbed_power_mgmt.h" + +using namespace std::chrono; + +enet_handle_t g_handle; +// RX packet buffer pointers +emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; +// TX packet buffer pointers +emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; +// RX packet payload pointers +uint32_t *rx_ptr[ENET_RX_RING_LEN]; + +/******************************************************************************** + * Internal data + ********************************************************************************/ +#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) +#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) + +extern "C" void kinetis_init_eth_hardware(void); + +/* \brief Flags for worker thread */ +#define FLAG_TX 1 +#define FLAG_RX 2 + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityNormal) + +#define PHY_TASK_PERIOD 200ms + +Kinetis_EMAC::Kinetis_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} +/******************************************************************************** + * Buffer management + ********************************************************************************/ +/* + * This function will queue a new receive buffer + */ +static void update_read_buffer(uint8_t *buf) +{ + if (buf != NULL) { + g_handle.rxBdCurrent[0]->buffer = buf; + } + + /* Ensures buffer pointer is written before control. */ + __DMB(); + + /* Clears status. */ + g_handle.rxBdCurrent[0]->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; + + /* Sets the receive buffer descriptor with the empty flag. */ + g_handle.rxBdCurrent[0]->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; + + /* Increases the buffer descriptor to the next one. */ + if (g_handle.rxBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) { + g_handle.rxBdCurrent[0] = g_handle.rxBdBase[0]; + } else { + g_handle.rxBdCurrent[0]++; + } + + /* Ensures descriptor is written before kicking hardware. */ + __DSB(); + + /* Actives the receive buffer descriptor. */ + ENET->RDAR = ENET_RDAR_RDAR_MASK; +} + +/** \brief Free TX buffers that are complete + */ +void Kinetis_EMAC::tx_reclaim() +{ + /* Get exclusive access */ + TXLockMutex.lock(); + + // Traverse all descriptors, looking for the ones modified by the uDMA + while ((tx_consume_index != tx_produce_index) && + (!(g_handle.txBdDirty[0]->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { + memory_manager->free(tx_buff[tx_consume_index % ENET_TX_RING_LEN]); + if (g_handle.txBdDirty[0]->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { + g_handle.txBdDirty[0] = g_handle.txBdBase[0]; + } else { + g_handle.txBdDirty[0]++; + } + + tx_consume_index += 1; + xTXDCountSem.release(); + } + + /* Restore access */ + TXLockMutex.unlock(); +} + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt. + */ +void Kinetis_EMAC::rx_isr() +{ + if (thread) { + osThreadFlagsSet(thread, FLAG_RX); + } +} + +void Kinetis_EMAC::tx_isr() +{ + osThreadFlagsSet(thread, FLAG_TX); +} + +void Kinetis_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) +{ + Kinetis_EMAC *enet = static_cast(param); + switch (event) { + case kENET_RxEvent: + enet->rx_isr(); + break; + case kENET_TxEvent: + enet->tx_isr(); + break; + default: + break; + } +} + + +/** \brief Low level init of the MAC and PHY. + */ +bool Kinetis_EMAC::low_level_init_successful() +{ + uint8_t i; + uint32_t sysClock; + phy_speed_t phy_speed; + phy_duplex_t phy_duplex; + uint32_t phyAddr = 0; + enet_config_t config; + + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rx_desc_start_addr[ENET_RX_RING_LEN], ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t tx_desc_start_addr[ENET_TX_RING_LEN], ENET_BUFF_ALIGNMENT); + + /* Create buffers for each receive BD */ + for (i = 0; i < ENET_RX_RING_LEN; i++) { + rx_buff[i] = memory_manager->alloc_heap(ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), + ENET_BUFF_ALIGNMENT); + if (NULL == rx_buff[i]) { + return false; + } + + rx_ptr[i] = (uint32_t *)memory_manager->get_ptr(rx_buff[i]); + SCB_InvalidateDCache_by_Addr(rx_ptr[i], ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT)); + } + + tx_consume_index = tx_produce_index = 0; + + /* prepare the buffer configuration. */ + enet_buffer_config_t buffCfg = { + ENET_RX_RING_LEN, + ENET_TX_RING_LEN, + ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), + 0, + (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, + (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, + (uint8_t *) &rx_ptr, + NULL, + }; + + kinetis_init_eth_hardware(); + + sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); + + ENET_GetDefaultConfig(&config); + + if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) { + return false; + } + + /* Get link information from PHY */ + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); + /* Change the MII speed and duplex for actual link status. */ + config.miiSpeed = (enet_mii_speed_t)phy_speed; + config.miiDuplex = (enet_mii_duplex_t)phy_duplex; + config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; + config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; + config.macSpecialConfig = kENET_ControlFlowControlEnable; + config.txAccelerConfig = 0; + config.rxAccelerConfig = kENET_RxAccelMacCheckEnabled; + ENET_Init(ENET, &g_handle, &config, &buffCfg, hwaddr, sysClock); + + ENET_SetCallback(&g_handle, &Kinetis_EMAC::ethernet_callback, this); + ENET_ActiveRead(ENET); + + return true; +} + +/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. + * + * \param[in] idx index of packet to be read + * \return a emac_mem_buf_t filled with the received packet (including MAC header) + */ +emac_mem_buf_t *Kinetis_EMAC::low_level_input(int idx) +{ + volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent[0]; + emac_mem_buf_t *p = NULL; + emac_mem_buf_t *temp_rxbuf = NULL; + uint32_t length = 0; + const uint16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | + ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; + +#ifdef LOCK_RX_THREAD + /* Get exclusive access */ + TXLockMutex.lock(); +#endif + + /* Determine if a frame has been received */ + if ((bdPtr->control & err_mask) != 0) { + /* Re-use the same buffer in case of error */ + update_read_buffer(NULL); + } else { + /* A packet is waiting, get length */ + length = bdPtr->length; + + /* Zero-copy */ + p = rx_buff[idx]; + SCB_InvalidateDCache_by_Addr(rx_ptr[idx], length); + memory_manager->set_len(p, length); + + /* Attempt to queue new buffer */ + temp_rxbuf = memory_manager->alloc_heap(ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), + ENET_BUFF_ALIGNMENT); + if (NULL == temp_rxbuf) { + /* Re-queue the same buffer */ + update_read_buffer(NULL); + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + + return NULL; + } + + rx_buff[idx] = temp_rxbuf; + rx_ptr[idx] = (uint32_t *)memory_manager->get_ptr(rx_buff[idx]); + SCB_InvalidateDCache_by_Addr(rx_ptr[idx], ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT)); + + update_read_buffer((uint8_t *)rx_ptr[idx]); + } + +#ifdef LOCK_RX_THREAD + osMutexRelease(TXLockMutex); +#endif + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + * \param[in] idx index of packet to be read + */ +void Kinetis_EMAC::input(int idx) +{ + emac_mem_buf_t *p; + + /* move received packet into a new buf */ + p = low_level_input(idx); + if (p == NULL) { + return; + } + + emac_link_input_cb(p); +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void Kinetis_EMAC::thread_function(void *pvParameters) +{ + struct Kinetis_EMAC *kinetis_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); + + MBED_ASSERT(!(flags & osFlagsError)); + + if (flags & FLAG_RX) { + kinetis_enet->packet_rx(); + } + + if (flags & FLAG_TX) { + kinetis_enet->packet_tx(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + */ +void Kinetis_EMAC::packet_rx() +{ + static int idx = 0; + + while ((g_handle.rxBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { + input(idx); + idx = (idx + 1) % ENET_RX_RING_LEN; + } +} + +/** \brief Transmit cleanup task + * + * This task is called when a transmit interrupt occurs and + * reclaims the buffer and descriptor used for the packet once + * the packet has been transferred. + */ +void Kinetis_EMAC::packet_tx() +{ + tx_reclaim(); +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf) +{ + // If buffer is chained or not aligned then make a contiguous aligned copy of it + if (memory_manager->get_next(buf) || + reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + memory_manager->free(buf); + return false; + } + + // Copy to new buffer and free original + memory_manager->copy(copy_buf, buf); + memory_manager->free(buf); + buf = copy_buf; + } + + SCB_CleanDCache_by_Addr(static_cast(memory_manager->get_ptr(buf)), memory_manager->get_len(buf)); + + /* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */ + if (!xTXDCountSem.try_acquire_for(10)) { + memory_manager->free(buf); + return false; + } + + /* Get exclusive access */ + TXLockMutex.lock(); + + /* Save the buffer so that it can be freed when transmit is done */ + tx_buff[tx_produce_index % ENET_TX_RING_LEN] = buf; + tx_produce_index += 1; + + /* Setup transfers */ + g_handle.txBdCurrent[0]->buffer = static_cast(memory_manager->get_ptr(buf)); + g_handle.txBdCurrent[0]->length = memory_manager->get_len(buf); + /* Ensures buffer and length is written before control. */ + __DMB(); + g_handle.txBdCurrent[0]->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); + + /* Increase the buffer descriptor address. */ + if (g_handle.txBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { + g_handle.txBdCurrent[0] = g_handle.txBdBase[0]; + } else { + g_handle.txBdCurrent[0]++; + } + + /* Ensures descriptor is written before kicking hardware. */ + __DSB(); + + /* Active the transmit buffer descriptor. */ + ENET->TDAR = ENET_TDAR_TDAR_MASK; + + /* Restore access */ + TXLockMutex.unlock(); + + return true; +} + +/******************************************************************************* + * PHY task: monitor link +*******************************************************************************/ + +#define STATE_UNKNOWN (-1) +#define STATE_LINK_DOWN (0) +#define STATE_LINK_UP (1) + +void Kinetis_EMAC::phy_task() +{ + uint32_t phyAddr = BOARD_ENET_PHY_ADDR; + + // Get current status + PHY_STATE crt_state; + bool connection_status; + PHY_GetLinkStatus(ENET, phyAddr, &connection_status); + + if (connection_status) { + crt_state.connected = STATE_LINK_UP; + } else { + crt_state.connected = STATE_LINK_DOWN; + } + + if (crt_state.connected == STATE_LINK_UP) { + if (prev_state.connected != STATE_LINK_UP) { + PHY_AutoNegotiation(ENET, phyAddr); + } + + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); + + if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) { + /* Poke the registers*/ + ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex); + } + } + + // Compare with previous state + if (crt_state.connected != prev_state.connected && emac_link_state_cb) { + emac_link_state_cb(crt_state.connected); + } + + prev_state = crt_state; +} + +bool Kinetis_EMAC::power_up() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + // Can't enter deep sleep as long as Ethernet is active + sleep_manager_lock_deep_sleep(); + + /* Worker thread */ + thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); + + /* Trigger thread to deal with any RX packets that arrived before thread was started */ + rx_isr(); + + /* PHY monitoring task */ + prev_state.connected = STATE_LINK_DOWN; + prev_state.speed = (phy_speed_t)STATE_UNKNOWN; + prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; + + mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &Kinetis_EMAC::phy_task)); + + return true; +} + +uint32_t Kinetis_EMAC::get_mtu_size() const +{ + return KINETIS_ETH_MTU_SIZE; +} + +uint32_t Kinetis_EMAC::get_align_preference() const +{ + return ENET_BUFF_ALIGNMENT; +} + +void Kinetis_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, KINETIS_ETH_IF_NAME, (size < sizeof(KINETIS_ETH_IF_NAME)) ? size : sizeof(KINETIS_ETH_IF_NAME)); +} + +uint8_t Kinetis_EMAC::get_hwaddr_size() const +{ + return KINETIS_HWADDR_SIZE; +} + +bool Kinetis_EMAC::get_hwaddr(uint8_t *addr) const +{ + return false; +} + +void Kinetis_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, sizeof hwaddr); + ENET_SetMacAddr(ENET, const_cast(addr)); +} + +void Kinetis_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void Kinetis_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void Kinetis_EMAC::add_multicast_group(const uint8_t *addr) +{ + ENET_AddMulticastGroup(ENET, const_cast(addr)); +} + +void Kinetis_EMAC::remove_multicast_group(const uint8_t *addr) +{ + // ENET HAL doesn't reference count - ENET_LeaveMulticastGroup just maps + // address to filter bit, and clears that bit, even if shared by other + // addresses. So don't attempt anything for now. +} + +void Kinetis_EMAC::set_all_multicast(bool all) +{ + if (all) { + ENET->GAUR = 0xFFFFFFFFu; + ENET->GALR = 0xFFFFFFFFu; + } +} + +void Kinetis_EMAC::power_down() +{ + // Ethernet went down, can enter deep sleep + sleep_manager_unlock_deep_sleep(); +} + +void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +Kinetis_EMAC &Kinetis_EMAC::get_instance() +{ + static Kinetis_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return Kinetis_EMAC::get_instance(); +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ + diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h new file mode 100644 index 0000000..82b588b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KINETIS_EMAC_H_ +#define KINETIS_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class Kinetis_EMAC : public EMAC { +public: + Kinetis_EMAC(); + + static Kinetis_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + bool low_level_init_successful(); + void rx_isr(); + void tx_isr(); + void packet_rx(); + void packet_tx(); + void tx_reclaim(); + void input(int idx); + emac_mem_buf_t *low_level_input(int idx); + static void thread_function(void* pvParameters); + void phy_task(); + static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param); + + mbed_rtos_storage_thread_t thread_cb; + osThreadId_t thread; /**< Processing thread */ + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ + uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + int phy_task_handle; /**< Handle for phy task event */ + struct PHY_STATE { + int connected; + phy_speed_t speed; + phy_duplex_t duplex; + }; + PHY_STATE prev_state; + uint8_t hwaddr[KINETIS_HWADDR_SIZE]; +}; + +#endif /* KINETIS_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h new file mode 100644 index 0000000..a56fe41 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef KINETIS_EMAC_CONFIG_H__ +#define KINETIS_EMAC_CONFIG_H__ + +#include "fsl_enet.h" + +#define ENET_RX_RING_LEN MBED_CONF_KINETIS_EMAC_RX_RING_LEN +#define ENET_TX_RING_LEN MBED_CONF_KINETIS_EMAC_TX_RING_LEN + +#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame + +#define KINETIS_HWADDR_SIZE (6) + +#define KINETIS_ETH_MTU_SIZE 1500 +#define KINETIS_ETH_IF_NAME "en" + +#define THREAD_STACKSIZE 512 + +#endif // #define KINETIS_EMAC_CONFIG_H__ + diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json new file mode 100644 index 0000000..2e1ef2e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json @@ -0,0 +1,7 @@ +{ + "name": "kinetis-emac", + "config": { + "rx-ring-len": 16, + "tx-ring-len": 8 + } +} diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp new file mode 100644 index 0000000..76cbe38 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp @@ -0,0 +1,941 @@ +/********************************************************************** +* $Id$ lpc17_emac.c 2011-11-20 +*//** +* @file lpc17_emac.c +* @brief LPC17 ethernet driver for LWIP +* @version 1.0 +* @date 20. Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#include +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" + +#include "lpc_emac_config.h" +#include "lpc17_emac.h" +#include "lpc17xx_emac.h" +#include "lpc_phy.h" +#include "mbed_interface.h" + +#ifndef LPC_EMAC_RMII +#error LPC_EMAC_RMII is not defined! +#endif + +#if LPC_NUM_BUFF_TXDESCS < 2 +#error LPC_NUM_BUFF_TXDESCS must be at least 2 +#endif + +#if LPC_NUM_BUFF_RXDESCS < 3 +#error LPC_NUM_BUFF_RXDESCS must be at least 3 +#endif + +/** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP + * @ingroup lwip_emac + * + * @{ + */ + +/** \brief Driver transmit and receive thread priorities + * + * Thread priorities for receive thread and TX cleanup thread. Alter + * to prioritize receive or transmit bandwidth. In a heavily loaded + * system or with LEIP_DEBUG enabled, the priorities might be better + * the same. */ +#define RX_PRIORITY (osPriorityNormal) +#define TX_PRIORITY (osPriorityNormal) +#define PHY_PRIORITY (osPriorityNormal) + +/** \brief Debug output formatter lock define + * + * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this + * define will allow RX debug messages to not interleave with the + * TX messages (so they are actually readable). Not enabling this + * define when the system is under load will cause the output to + * be unreadable. There is a small tradeoff in performance for this + * so use it only for debug. */ +//#define LOCK_RX_THREAD + +/** \brief Receive group interrupts + */ +#define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE) + +/** \brief Transmit group interrupts + */ +#define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE) + +/** \brief Signal used for ethernet ISR to signal packet_rx() thread. + */ +#define RX_SIGNAL 1 + + /** \brief Structure of a TX/RX descriptor + */ +typedef struct +{ + volatile uint32_t packet; /**< Pointer to buffer */ + volatile uint32_t control; /**< Control word */ +} LPC_TXRX_DESC_T; + +/** \brief Structure of a RX status entry + */ +typedef struct +{ + volatile uint32_t statusinfo; /**< RX status word */ + volatile uint32_t statushashcrc; /**< RX hash CRC */ +} LPC_TXRX_STATUS_T; + +/* LPC EMAC driver data structure */ +struct lpc_enetdata { + /* prxs must be 8 byte aligned! */ + LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */ + LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */ + LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */ + LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */ + emac_mem_buf_t *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */ + uint32_t rx_fill_desc_index; /**< RX descriptor next available index */ + volatile uint32_t rx_free_descs; /**< Count of free RX descriptors */ + emac_mem_buf_t *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */ + uint32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */ + uint32_t lpc_reserved_tx_num; /**< Number of reserved TX descriptors, zero-copy mode */ +}; + +#if defined(TARGET_LPC1768) +/** \brief Group LPC17xx processors into one definition + */ +#define TARGET_LPC17XX +#endif + +#if defined(TARGET_LPC17XX) +# if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_ARM) +# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) +# endif +#endif + +#ifndef ETHMEM_SECTION +#define ETHMEM_SECTION +#endif + +/** \brief LPC EMAC driver work data + */ +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#pragma data_alignment = 8 +#endif +ETHMEM_SECTION struct lpc_enetdata lpc_enetdata; + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#pragma data_alignment = 8 +#endif +ETHMEM_SECTION uint8_t rx_thread_stack[DEFAULT_THREAD_STACKSIZE]; + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#pragma data_alignment = 8 +#endif +ETHMEM_SECTION uint8_t tx_clean_thread_stack[DEFAULT_THREAD_STACKSIZE]; + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#pragma data_alignment = 8 +#endif +ETHMEM_SECTION uint8_t phy_thread_stack[DEFAULT_THREAD_STACKSIZE]; + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, void *stack_ptr, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = stack_ptr; + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} + +/** \brief Queues a memory buffer into the RX descriptor list + * + * \param[in] p Pointer to buffer to queue + */ +void LPC17_EMAC::lpc_rxqueue_pbuf(emac_mem_buf_t *p) +{ + uint32_t idx; + + /* Get next free descriptor index */ + idx = lpc_enetdata.rx_fill_desc_index; + + /* Setup descriptor and clear statuses */ + lpc_enetdata.prxd[idx].control = EMAC_RCTRL_INT | ((uint32_t) (memory_manager->get_len(p) - 1)); + lpc_enetdata.prxd[idx].packet = (uint32_t) memory_manager->get_ptr(p); + lpc_enetdata.prxs[idx].statusinfo = 0xFFFFFFFF; + lpc_enetdata.prxs[idx].statushashcrc = 0xFFFFFFFF; + + /* Save pbuf pointer for push to network layer later */ + lpc_enetdata.rxb[idx] = p; + + /* Wrap at end of descriptor list */ + idx++; + if (idx >= LPC_NUM_BUFF_RXDESCS) { + idx = 0; + } + + /* Queue descriptor(s) */ + lpc_enetdata.rx_free_descs -= 1; + lpc_enetdata.rx_fill_desc_index = idx; + LPC_EMAC->RxConsumeIndex = idx; +} + +/** \brief Attempt to allocate and requeue a new memory buffer for RX + * + * \returns >= 1 if a packet or packets were allocated and requeued, otherwise 0 + */ +int32_t LPC17_EMAC::lpc_rx_queue() +{ + //struct lpc_enetdata *lpc_enetif = netif->state; + emac_mem_buf_t *p; + int32_t queued = 0; + + /* Attempt to requeue as many packets as possible */ + while (lpc_enetdata.rx_free_descs > 0) { + /* Allocate a pbuf from the pool. We need to allocate at the + maximum size as we don't know the size of the yet to be + received packet. */ + p = memory_manager->alloc_heap(EMAC_ETH_MAX_FLEN, 0); + if (p == NULL) { + return queued; + } + + /* Queue packet */ + lpc_rxqueue_pbuf(p); + + /* Update queued count */ + queued++; + } + + return queued; +} + +/** \brief Sets up the RX descriptor ring buffers. + * + * This function sets up the descriptor list used for receive packets. + * + * \returns Always returns ERR_OK + */ +bool LPC17_EMAC::lpc_rx_setup() +{ + /* Setup pointers to RX structures */ + LPC_EMAC->RxDescriptor = (uint32_t) &lpc_enetdata.prxd[0]; + LPC_EMAC->RxStatus = (uint32_t) &lpc_enetdata.prxs[0]; + LPC_EMAC->RxDescriptorNumber = LPC_NUM_BUFF_RXDESCS - 1; + + lpc_enetdata.rx_free_descs = LPC_NUM_BUFF_RXDESCS; + lpc_enetdata.rx_fill_desc_index = 0; + + /* Build RX buffer and descriptors */ + lpc_rx_queue(); + + return true; +} + +/** \brief Allocates a memory buffer and returns the data from the incoming packet. + * + * \return a buffer filled with the received packet (including MAC header) + * NULL on memory error + */ +emac_mem_buf_t *LPC17_EMAC::lpc_low_level_input() +{ + emac_mem_buf_t *p = NULL; + uint32_t idx, length; + uint16_t origLength; + +#ifdef LOCK_RX_THREAD + TXLockMutex.lock(); +#endif + + /* Monitor RX overrun status. This should never happen unless + (possibly) the internal bus is behing held up by something. + Unless your system is running at a very low clock speed or + there are possibilities that the internal buses may be held + up for a long time, this can probably safely be removed. */ + if (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) { + + /* Temporarily disable RX */ + LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN; + + /* Reset the RX side */ + LPC_EMAC->MAC1 |= EMAC_MAC1_RES_RX; + LPC_EMAC->IntClear = EMAC_INT_RX_OVERRUN; + + /* De-allocate all queued RX pbufs */ + for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) { + if (lpc_enetdata.rxb[idx] != NULL) { + memory_manager->free(lpc_enetdata.rxb[idx]); + lpc_enetdata.rxb[idx] = NULL; + } + } + + /* Start RX side again */ + lpc_rx_setup(); + + /* Re-enable RX */ + LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + return NULL; + } + + /* Determine if a frame has been received */ + length = 0; + idx = LPC_EMAC->RxConsumeIndex; + + if (LPC_EMAC->RxProduceIndex != idx) { + /* Handle errors */ + if (lpc_enetdata.prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR | + EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) { + + /* Re-queue the buffer for receive */ + lpc_enetdata.rx_free_descs++; + p = lpc_enetdata.rxb[idx]; + lpc_enetdata.rxb[idx] = NULL; + lpc_rxqueue_pbuf(p); + + p = NULL; + } else { + /* A packet is waiting, get length */ + length = (lpc_enetdata.prxs[idx].statusinfo & 0x7FF) + 1; + length -= 4; + + /* Zero-copy */ + p = lpc_enetdata.rxb[idx]; + origLength = memory_manager->get_len(p); + memory_manager->set_len(p, length); + + /* Free buffer from descriptor */ + lpc_enetdata.rxb[idx] = NULL; + lpc_enetdata.rx_free_descs++; + + /* Attempt to queue new buffer(s) */ + if (lpc_rx_queue() == 0) { + /* Re-queue the buffer for receive */ + memory_manager->set_len(p, origLength); + lpc_rxqueue_pbuf(p); + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + return NULL; + } + } + } + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +void LPC17_EMAC::lpc_enetif_input() +{ + emac_mem_buf_t *p; + + /* move received packet into a new memory buffer */ + p = lpc_low_level_input(); + if (p == NULL) { + return; + } + + emac_link_input_cb(p); +} + +/** \brief Determine if the passed address is usable for the ethernet + * DMA controller. + * + * \param[in] addr Address of packet to check for DMA safe operation + * \return 1 if the packet address is not safe, otherwise 0 + */ +int32_t LPC17_EMAC::lpc_packet_addr_notsafe(void *addr) +{ + /* Check for legal address ranges */ +#if defined(TARGET_LPC17XX) + if ((((uint32_t) addr >= 0x2007C000) && ((uint32_t) addr < 0x20083FFF))) { +#endif + return 0; + } + return 1; +} + +/** \brief Sets up the TX descriptor ring buffers. + * + * This function sets up the descriptor list used for transmit packets. + */ +bool LPC17_EMAC::lpc_tx_setup() +{ + int32_t idx; + + /* Build TX descriptors for local buffers */ + for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { + lpc_enetdata.ptxd[idx].control = 0; + lpc_enetdata.ptxs[idx].statusinfo = 0xFFFFFFFF; + } + + /* Setup pointers to TX structures */ + LPC_EMAC->TxDescriptor = (uint32_t) &lpc_enetdata.ptxd[0]; + LPC_EMAC->TxStatus = (uint32_t) &lpc_enetdata.ptxs[0]; + LPC_EMAC->TxDescriptorNumber = LPC_NUM_BUFF_TXDESCS - 1; + + lpc_enetdata.lpc_last_tx_idx = 0; + lpc_enetdata.lpc_reserved_tx_num = 0; + + return true; +} + +/** \brief Free TX buffers that are complete + * + * \param[in] cidx EMAC current descriptor comsumer index + */ +void LPC17_EMAC::lpc_tx_reclaim_st(uint32_t cidx) +{ + TXLockMutex.lock(); + + // If consume index not last freed index or all descriptors in use + while (cidx != lpc_enetdata.lpc_last_tx_idx || lpc_enetdata.lpc_reserved_tx_num == LPC_NUM_BUFF_TXDESCS) { + if (lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] != NULL) { + memory_manager->free(lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx]); + lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] = NULL; + } + + xTXDCountSem.release(); + + lpc_enetdata.lpc_last_tx_idx++; + if (lpc_enetdata.lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS) { + lpc_enetdata.lpc_last_tx_idx = 0; + } + lpc_enetdata.lpc_reserved_tx_num--; + } + + TXLockMutex.unlock(); +} + +/** \brief User call for freeingTX buffers that are complete + * + */ +void LPC17_EMAC::lpc_tx_reclaim() +{ + lpc_tx_reclaim_st(LPC_EMAC->TxConsumeIndex); +} + + /** \brief Polls if an available TX descriptor is ready. Can be used to + * determine if the low level transmit function will block. + * + * \return 0 if no descriptors are read, or >0 + */ +int32_t LPC17_EMAC::lpc_tx_ready() +{ + int32_t fb; + uint32_t idx, cidx; + + cidx = LPC_EMAC->TxConsumeIndex; + idx = LPC_EMAC->TxProduceIndex; + + /* Determine number of free buffers */ + if (idx == cidx) { + fb = LPC_NUM_BUFF_TXDESCS; + } else if (cidx > idx) { + fb = (LPC_NUM_BUFF_TXDESCS - 1) - + ((idx + LPC_NUM_BUFF_TXDESCS) - cidx); + } else { + fb = (LPC_NUM_BUFF_TXDESCS - 1) - (cidx - idx); + } + + return fb; +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +bool LPC17_EMAC::link_out(emac_mem_buf_t *p) +{ + emac_mem_buf_t *q; + uint32_t idx, notdmasafe = 0; + emac_mem_buf_t *np; + int32_t dn; + + /* Zero-copy TX buffers may be fragmented across a memory buffer chain. Determine + the number of descriptors needed for the transfer and make sure packet addresses + are DMA safe. + + A DMA safe address is once that uses external memory or periphheral RAM. + IRAM and FLASH are not safe! */ + dn = 0; + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + ++dn; + void *ptr = memory_manager->get_ptr(q); + notdmasafe += lpc_packet_addr_notsafe(ptr); + } + +#if LPC_TX_PBUF_BOUNCE_EN==1 + /* If the buffer chain is not DMA safe, a new bounce buffer will be + created that will be used instead. This requires an copy from the + non-safe DMA region to the new buffer. */ + if (notdmasafe) { + /* Allocate a buffer in DMA memory. + MEMORY MANAGER HEAP MUST BE IN DMA SAFE MEMORY. */ + np = memory_manager->alloc_heap(memory_manager->get_total_len(p), 0); + if (np == NULL) { + memory_manager->free(p); + return false; + } + memory_manager->copy(np, p); + /* use the new buffer for descriptor queueing. The original buffer will + be de-allocated. */ + memory_manager->free(p); + p = np; + dn = 1; + } +#else + if (notdmasafe) { + MBED_ASSERT(0); + } +#endif + + /* Wait until enough descriptors are available for the transfer. */ + /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */ + for (int32_t count = 0; count < dn; count++) { + xTXDCountSem.acquire(); + } + + MBED_ASSERT(dn <= lpc_tx_ready()); + + TXLockMutex.lock(); + + /* Get free TX buffer index */ + idx = LPC_EMAC->TxProduceIndex; + + /* Setup transfers */ + q = p; + while (dn > 0) { + dn--; + + /* Only save pointer to free on last descriptor */ + if (dn == 0) { + /* Save size of packet and signal it's ready */ + lpc_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT | + EMAC_TCTRL_LAST; + lpc_enetdata.txb[idx] = p; + } + else { + /* Save size of packet, descriptor is not last */ + lpc_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT; + lpc_enetdata.txb[idx] = NULL; + } + + lpc_enetdata.ptxd[idx].packet = (uint32_t) memory_manager->get_ptr(q); + + q = memory_manager->get_next(q); + + idx++; + if (idx >= LPC_NUM_BUFF_TXDESCS) { + idx = 0; + } + lpc_enetdata.lpc_reserved_tx_num++; + } + + LPC_EMAC->TxProduceIndex = idx; + + TXLockMutex.unlock(); + + return true; +} + +/** \brief LPC EMAC interrupt handler. + * + * This function handles the transmit, receive, and error interrupt of + * the LPC177x_8x. This is meant to be used when NO_SYS=0. + */ +void LPC17xxEthernetHandler(void) +{ + LPC17_EMAC &emac = LPC17_EMAC::get_instance(); + + uint32_t ints; + + /* Interrupts are of 2 groups - transmit or receive. Based on the + interrupt, kick off the receive or transmit (cleanup) task */ + + /* Get pending interrupts */ + ints = LPC_EMAC->IntStatus; + + if (ints & RXINTGROUP) { + /* RX group interrupt(s): Give signal to wakeup RX receive task.*/ + osThreadFlagsSet(emac.RxThread, RX_SIGNAL); + } + + if (ints & TXINTGROUP) { + /* TX group interrupt(s): Give semaphore to wakeup TX cleanup task. */ + emac.TxCleanSem.release(); + } + + /* Clear pending interrupts */ + LPC_EMAC->IntClear = ints; +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the IP stacks core. + * + * \param[in] pvParameters Not used yet + */ +void LPC17_EMAC::packet_rx(void* pvParameters) +{ + LPC17_EMAC *lpc17_emac = static_cast(pvParameters); + + while (1) { + /* Wait for receive task to wakeup */ + osThreadFlagsWait(RX_SIGNAL, 0, osWaitForever); + + /* Process packets until all empty */ + while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { + lpc17_emac->lpc_enetif_input(); + } + } +} + +/** \brief Transmit cleanup task + * + * This task is called when a transmit interrupt occurs and + * reclaims the memory buffer and descriptor used for the packet once + * the packet has been transferred. + * + * \param[in] pvParameters Not used yet + */ +void LPC17_EMAC::packet_tx(void* pvParameters) +{ + LPC17_EMAC *lpc17_emac = static_cast(pvParameters); + int32_t idx; + + while (1) { + /* Wait for transmit cleanup task to wakeup */ + lpc17_emac->TxCleanSem.acquire(); + + /* Error handling for TX underruns. This should never happen unless + something is holding the bus or the clocks are going too slow. It + can probably be safely removed. */ + if (LPC_EMAC->IntStatus & EMAC_INT_TX_UNDERRUN) { + lpc17_emac->TXLockMutex.lock(); + + /* Reset the TX side */ + LPC_EMAC->MAC1 |= EMAC_MAC1_RES_TX; + LPC_EMAC->IntClear = EMAC_INT_TX_UNDERRUN; + + /* De-allocate all queued TX buffers */ + for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { + if (lpc_enetdata.txb[idx] != NULL) { + lpc17_emac->memory_manager->free(lpc_enetdata.txb[idx]); + lpc_enetdata.txb[idx] = NULL; + } + } + + lpc17_emac->TXLockMutex.unlock(); + + /* Start TX side again */ + lpc17_emac->lpc_tx_setup(); + } else { + /* Free TX buffers that are done sending */ + lpc17_emac->lpc_tx_reclaim(); + } + } +} + +/** \brief Low level init of the MAC and PHY. + * + */ +bool LPC17_EMAC::low_level_init() +{ + bool err = true; + + /* Enable MII clocking */ + LPC_SC->PCONP |= CLKPWR_PCONP_PCENET; + +#if defined(TARGET_LPC17XX) + LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */ + LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005; +#endif + + /* Reset all MAC logic */ + LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | + EMAC_MAC1_RES_RX | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | + EMAC_MAC1_SOFT_RES; + LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | + EMAC_CR_PASS_RUNT_FRM; + osDelay(10); + + /* Initial MAC initialization */ + LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; + LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN | + EMAC_MAC2_VLAN_PAD_EN; + LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; + + /* Set RMII management clock rate to lowest speed */ + LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(11) | EMAC_MCFG_RES_MII; + LPC_EMAC->MCFG &= ~EMAC_MCFG_RES_MII; + + /* Maximum number of retries, 0x37 collision window, gap */ + LPC_EMAC->CLRT = EMAC_CLRT_DEF; + LPC_EMAC->IPGR = EMAC_IPGR_P1_DEF | EMAC_IPGR_P2_DEF; + +#if LPC_EMAC_RMII + /* RMII setup */ + LPC_EMAC->Command = EMAC_CR_PASS_RUNT_FRM | EMAC_CR_RMII; +#else + /* MII setup */ + LPC_EMAC->CR = EMAC_CR_PASS_RUNT_FRM; +#endif + + /* Initialize the PHY and reset */ + err = lpc_phy_init(this, LPC_EMAC_RMII); + if (err == false) { + return false; + } + + /* Save station address */ + LPC_EMAC->SA2 = (uint32_t) hwaddr[0] | + (((uint32_t) hwaddr[1]) << 8); + LPC_EMAC->SA1 = (uint32_t) hwaddr[2] | + (((uint32_t) hwaddr[3]) << 8); + LPC_EMAC->SA0 = (uint32_t) hwaddr[4] | + (((uint32_t) hwaddr[5]) << 8); + + /* Setup transmit and receive descriptors */ + if (lpc_tx_setup() != true) { + return false; + } + if (lpc_rx_setup() != true) { + return false; + } + + /* Enable packet reception */ + LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_MCAST_EN; + + /* Clear and enable rx/tx interrupts */ + LPC_EMAC->IntClear = 0xFFFF; + LPC_EMAC->IntEnable = RXINTGROUP | TXINTGROUP; + + /* Enable RX and TX */ + LPC_EMAC->Command |= EMAC_CR_RX_EN | EMAC_CR_TX_EN; + LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; + + return err; +} + +/* This function provides a method for the PHY to setup the EMAC + for the PHY negotiated duplex mode */ +void lpc_emac_set_duplex(int full_duplex) +{ + if (full_duplex) { + LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; + LPC_EMAC->Command |= EMAC_CR_FULL_DUP; + LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; + } else { + LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP; + LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP; + LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; + } +} + +/* This function provides a method for the PHY to setup the EMAC + for the PHY negotiated bit rate */ +void lpc_emac_set_speed(int mbs_100) +{ + if (mbs_100) { + LPC_EMAC->SUPP = EMAC_SUPP_SPEED; + } else { + LPC_EMAC->SUPP = 0; + } +} + +/* periodic PHY status update */ +void LPC17_EMAC::phy_update(void *nif) +{ + LPC17_EMAC *lpc17_emac = static_cast(nif); + + while (true) { + lpc_phy_sts_sm(lpc17_emac); + osDelay(250); + } +} + +void LPC17_EMAC::update_link_status(bool up) +{ + emac_link_state_cb(up); +} + +void LPC17_EMAC::eth_arch_enable_interrupts(void) { + NVIC_SetVector(ENET_IRQn, (uint32_t)LPC17xxEthernetHandler); + NVIC_SetPriority(ENET_IRQn, ((0x01 << 3) | 0x01)); + NVIC_EnableIRQ(ENET_IRQn); +} + +void LPC17_EMAC::eth_arch_disable_interrupts(void) { + NVIC_DisableIRQ(ENET_IRQn); +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. + * + * This function should be passed as a parameter to netif_add(). + * + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +bool LPC17_EMAC::power_up() +{ + bool err = low_level_init(); + if (err != true) { + return false; + } + + RxThread = create_new_thread("lpc17_emac_rx_thread", LPC17_EMAC::packet_rx, this, rx_thread_stack, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &RxThread_cb); + TxCleanThread = create_new_thread("lpc17_emac_txclean_thread", LPC17_EMAC::packet_tx, this, tx_clean_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &TxCleanThread_cb); + PhyThread = create_new_thread("lpc17_emac_phy_thread", LPC17_EMAC::phy_update, this, phy_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &PhyThread_cb); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + eth_arch_enable_interrupts(); + + return true; +} + +uint32_t LPC17_EMAC::get_mtu_size() const +{ + return 1500; +} + +uint32_t LPC17_EMAC::get_align_preference() const +{ + return 0; +} + +void LPC17_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, LPC17_ETH_IF_NAME, (size < sizeof(LPC17_ETH_IF_NAME)) ? size : sizeof(LPC17_ETH_IF_NAME)); +} + +uint8_t LPC17_EMAC::get_hwaddr_size() const +{ + return LPC17_ETH_HWADDR_SIZE; +} + +bool LPC17_EMAC::get_hwaddr(uint8_t *addr) const +{ + return false; +} + +void LPC17_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, LPC17_ETH_HWADDR_SIZE); + + /* Save station address */ + LPC_EMAC->SA2 = (uint32_t) hwaddr[0] | + (((uint32_t) hwaddr[1]) << 8); + LPC_EMAC->SA1 = (uint32_t) hwaddr[2] | + (((uint32_t) hwaddr[3]) << 8); + LPC_EMAC->SA0 = (uint32_t) hwaddr[4] | + (((uint32_t) hwaddr[5]) << 8); +} + +void LPC17_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void LPC17_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void LPC17_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void LPC17_EMAC::remove_multicast_group(const uint8_t *address) +{ + /* No-op at this stage */ +} + +void LPC17_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void LPC17_EMAC::power_down() +{ + /* No-op at this stage */ +} + +LPC17_EMAC::LPC17_EMAC() + : RxThread(), + RxThread_cb(), + TxCleanSem(), + hwaddr(), + TxCleanThread(), + TxCleanThread_cb(), + PhyThread(), + PhyThread_cb(), + TXLockMutex(), + xTXDCountSem(LPC_NUM_BUFF_TXDESCS), + emac_link_input_cb(0), + emac_link_state_cb(0), + memory_manager(0) +{ +} + +void LPC17_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +LPC17_EMAC &LPC17_EMAC::get_instance() { + static LPC17_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() { + return LPC17_EMAC::get_instance(); +} + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h new file mode 100644 index 0000000..87ca062 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h @@ -0,0 +1,191 @@ +/* Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LPC17_EMAC_H_ +#define LPC17_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +#include "lpc_emac_config.h" + +class LPC17_EMAC : public EMAC { +public: + LPC17_EMAC(); + + static LPC17_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + void update_link_status(bool up); + + osThreadId_t RxThread; + mbed_rtos_storage_thread_t RxThread_cb; + rtos::Semaphore TxCleanSem; + +private: + void lpc_rxqueue_pbuf(emac_mem_buf_t *p); + int32_t lpc_rx_queue(); + bool lpc_rx_setup(); + emac_mem_buf_t *lpc_low_level_input(); + void lpc_enetif_input(); + int32_t lpc_packet_addr_notsafe(void *addr); + bool lpc_tx_setup(); + void lpc_tx_reclaim_st(uint32_t cidx); + void lpc_tx_reclaim(); + int32_t lpc_tx_ready(); + static void packet_rx(void* pvParameters); + static void packet_tx(void* pvParameters); + bool low_level_init(); + static void phy_update(void *nif); + bool eth_arch_enetif_init(); + void eth_arch_enable_interrupts(); + void eth_arch_disable_interrupts(); + + uint8_t hwaddr[6]; + + osThreadId_t TxCleanThread; + mbed_rtos_storage_thread_t TxCleanThread_cb; + osThreadId_t PhyThread; + mbed_rtos_storage_thread_t PhyThread_cb; + rtos::Mutex TXLockMutex; + rtos::Semaphore xTXDCountSem; + + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + + EMACMemoryManager *memory_manager; /**< Memory manager */ +}; + +#endif diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h new file mode 100644 index 0000000..13019d4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h @@ -0,0 +1,665 @@ +/********************************************************************** +* $Id$ lpc17xx_emac.h 2010-05-21 +*//** +* @file lpc17xx_emac.h +* @brief Contains all macro definitions and function prototypes +* support for Ethernet MAC firmware library on LPC17xx +* @version 2.0 +* @date 21. May. 2010 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2010, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +/* Peripheral group ----------------------------------------------------------- */ +/** @defgroup EMAC EMAC (Ethernet Media Access Controller) + * @ingroup LPC1700CMSIS_FwLib_Drivers + * @{ + */ + +#ifndef LPC17XX_EMAC_H_ +#define LPC17XX_EMAC_H_ + +/* Includes ------------------------------------------------------------------- */ +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define MCB_LPC_1768 +//#define IAR_LPC_1768 + +/* Public Macros -------------------------------------------------------------- */ +/** @defgroup EMAC_Public_Macros EMAC Public Macros + * @{ + */ + + +/* EMAC PHY status type definitions */ +#define EMAC_PHY_STAT_LINK (0) /**< Link Status */ +#define EMAC_PHY_STAT_SPEED (1) /**< Speed Status */ +#define EMAC_PHY_STAT_DUP (2) /**< Duplex Status */ + +/* EMAC PHY device Speed definitions */ +#define EMAC_MODE_AUTO (0) /**< Auto-negotiation mode */ +#define EMAC_MODE_10M_FULL (1) /**< 10Mbps FullDuplex mode */ +#define EMAC_MODE_10M_HALF (2) /**< 10Mbps HalfDuplex mode */ +#define EMAC_MODE_100M_FULL (3) /**< 100Mbps FullDuplex mode */ +#define EMAC_MODE_100M_HALF (4) /**< 100Mbps HalfDuplex mode */ + +/** + * @} + */ +/* Private Macros ------------------------------------------------------------- */ +/** @defgroup EMAC_Private_Macros EMAC Private Macros + * @{ + */ + + +/* EMAC Memory Buffer configuration for 16K Ethernet RAM */ +#define EMAC_NUM_RX_FRAG 4 /**< Num.of RX Fragments 4*1536= 6.0kB */ +#define EMAC_NUM_TX_FRAG 3 /**< Num.of TX Fragments 3*1536= 4.6kB */ +#define EMAC_ETH_MAX_FLEN 1536 /**< Max. Ethernet Frame Size */ +#define EMAC_TX_FRAME_TOUT 0x00100000 /**< Frame Transmit timeout count */ + +/* --------------------- BIT DEFINITIONS -------------------------------------- */ +/*********************************************************************//** + * Macro defines for MAC Configuration Register 1 + **********************************************************************/ +#define EMAC_MAC1_REC_EN 0x00000001 /**< Receive Enable */ +#define EMAC_MAC1_PASS_ALL 0x00000002 /**< Pass All Receive Frames */ +#define EMAC_MAC1_RX_FLOWC 0x00000004 /**< RX Flow Control */ +#define EMAC_MAC1_TX_FLOWC 0x00000008 /**< TX Flow Control */ +#define EMAC_MAC1_LOOPB 0x00000010 /**< Loop Back Mode */ +#define EMAC_MAC1_RES_TX 0x00000100 /**< Reset TX Logic */ +#define EMAC_MAC1_RES_MCS_TX 0x00000200 /**< Reset MAC TX Control Sublayer */ +#define EMAC_MAC1_RES_RX 0x00000400 /**< Reset RX Logic */ +#define EMAC_MAC1_RES_MCS_RX 0x00000800 /**< Reset MAC RX Control Sublayer */ +#define EMAC_MAC1_SIM_RES 0x00004000 /**< Simulation Reset */ +#define EMAC_MAC1_SOFT_RES 0x00008000 /**< Soft Reset MAC */ + +/*********************************************************************//** + * Macro defines for MAC Configuration Register 2 + **********************************************************************/ +#define EMAC_MAC2_FULL_DUP 0x00000001 /**< Full-Duplex Mode */ +#define EMAC_MAC2_FRM_LEN_CHK 0x00000002 /**< Frame Length Checking */ +#define EMAC_MAC2_HUGE_FRM_EN 0x00000004 /**< Huge Frame Enable */ +#define EMAC_MAC2_DLY_CRC 0x00000008 /**< Delayed CRC Mode */ +#define EMAC_MAC2_CRC_EN 0x00000010 /**< Append CRC to every Frame */ +#define EMAC_MAC2_PAD_EN 0x00000020 /**< Pad all Short Frames */ +#define EMAC_MAC2_VLAN_PAD_EN 0x00000040 /**< VLAN Pad Enable */ +#define EMAC_MAC2_ADET_PAD_EN 0x00000080 /**< Auto Detect Pad Enable */ +#define EMAC_MAC2_PPREAM_ENF 0x00000100 /**< Pure Preamble Enforcement */ +#define EMAC_MAC2_LPREAM_ENF 0x00000200 /**< Long Preamble Enforcement */ +#define EMAC_MAC2_NO_BACKOFF 0x00001000 /**< No Backoff Algorithm */ +#define EMAC_MAC2_BACK_PRESSURE 0x00002000 /**< Backoff Presurre / No Backoff */ +#define EMAC_MAC2_EXCESS_DEF 0x00004000 /**< Excess Defer */ + +/*********************************************************************//** + * Macro defines for Back-to-Back Inter-Packet-Gap Register + **********************************************************************/ +/** Programmable field representing the nibble time offset of the minimum possible period + * between the end of any transmitted packet to the beginning of the next */ +#define EMAC_IPGT_BBIPG(n) (n&0x7F) +/** Recommended value for Full Duplex of Programmable field representing the nibble time + * offset of the minimum possible period between the end of any transmitted packet to the + * beginning of the next */ +#define EMAC_IPGT_FULL_DUP (EMAC_IPGT_BBIPG(0x15)) +/** Recommended value for Half Duplex of Programmable field representing the nibble time + * offset of the minimum possible period between the end of any transmitted packet to the + * beginning of the next */ +#define EMAC_IPGT_HALF_DUP (EMAC_IPGT_BBIPG(0x12)) + +/*********************************************************************//** + * Macro defines for Non Back-to-Back Inter-Packet-Gap Register + **********************************************************************/ +/** Programmable field representing the Non-Back-to-Back Inter-Packet-Gap */ +#define EMAC_IPGR_NBBIPG_P2(n) (n&0x7F) +/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 1 */ +#define EMAC_IPGR_P2_DEF (EMAC_IPGR_NBBIPG_P2(0x12)) +/** Programmable field representing the optional carrierSense window referenced in + * IEEE 802.3/4.2.3.2.1 'Carrier Deference' */ +#define EMAC_IPGR_NBBIPG_P1(n) ((n&0x7F)<<8) +/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 2 */ +#define EMAC_IPGR_P1_DEF EMAC_IPGR_NBBIPG_P1(0x0C) + +/*********************************************************************//** + * Macro defines for Collision Window/Retry Register + **********************************************************************/ +/** Programmable field specifying the number of retransmission attempts following a collision before + * aborting the packet due to excessive collisions */ +#define EMAC_CLRT_MAX_RETX(n) (n&0x0F) +/** Programmable field representing the slot time or collision window during which collisions occur + * in properly configured networks */ +#define EMAC_CLRT_COLL(n) ((n&0x3F)<<8) +/** Default value for Collision Window / Retry register */ +#define EMAC_CLRT_DEF ((EMAC_CLRT_MAX_RETX(0x0F))|(EMAC_CLRT_COLL(0x37))) + +/*********************************************************************//** + * Macro defines for Maximum Frame Register + **********************************************************************/ +/** Represents a maximum receive frame of 1536 octets */ +#define EMAC_MAXF_MAXFRMLEN(n) (n&0xFFFF) + +/*********************************************************************//** + * Macro defines for PHY Support Register + **********************************************************************/ +#define EMAC_SUPP_SPEED 0x00000100 /**< Reduced MII Logic Current Speed */ +#define EMAC_SUPP_RES_RMII 0x00000800 /**< Reset Reduced MII Logic */ + +/*********************************************************************//** + * Macro defines for Test Register + **********************************************************************/ +#define EMAC_TEST_SHCUT_PQUANTA 0x00000001 /**< Shortcut Pause Quanta */ +#define EMAC_TEST_TST_PAUSE 0x00000002 /**< Test Pause */ +#define EMAC_TEST_TST_BACKP 0x00000004 /**< Test Back Pressure */ + +/*********************************************************************//** + * Macro defines for MII Management Configuration Register + **********************************************************************/ +#define EMAC_MCFG_SCAN_INC 0x00000001 /**< Scan Increment PHY Address */ +#define EMAC_MCFG_SUPP_PREAM 0x00000002 /**< Suppress Preamble */ +#define EMAC_MCFG_CLK_SEL(n) ((n&0x0F)<<2) /**< Clock Select Field */ +#define EMAC_MCFG_RES_MII 0x00008000 /**< Reset MII Management Hardware */ +#define EMAC_MCFG_MII_MAXCLK 2500000UL /**< MII Clock max */ + +/*********************************************************************//** + * Macro defines for MII Management Command Register + **********************************************************************/ +#define EMAC_MCMD_READ 0x00000001 /**< MII Read */ +#define EMAC_MCMD_SCAN 0x00000002 /**< MII Scan continuously */ + +#define EMAC_MII_WR_TOUT 0x00050000 /**< MII Write timeout count */ +#define EMAC_MII_RD_TOUT 0x00050000 /**< MII Read timeout count */ + +/*********************************************************************//** + * Macro defines for MII Management Address Register + **********************************************************************/ +#define EMAC_MADR_REG_ADR(n) (n&0x1F) /**< MII Register Address field */ +#define EMAC_MADR_PHY_ADR(n) ((n&0x1F)<<8) /**< PHY Address Field */ + +/*********************************************************************//** + * Macro defines for MII Management Write Data Register + **********************************************************************/ +#define EMAC_MWTD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Write Data register */ + +/*********************************************************************//** + * Macro defines for MII Management Read Data Register + **********************************************************************/ +#define EMAC_MRDD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Read Data register */ + +/*********************************************************************//** + * Macro defines for MII Management Indicators Register + **********************************************************************/ +#define EMAC_MIND_BUSY 0x00000001 /**< MII is Busy */ +#define EMAC_MIND_SCAN 0x00000002 /**< MII Scanning in Progress */ +#define EMAC_MIND_NOT_VAL 0x00000004 /**< MII Read Data not valid */ +#define EMAC_MIND_MII_LINK_FAIL 0x00000008 /**< MII Link Failed */ + +/* Station Address 0 Register */ +/* Station Address 1 Register */ +/* Station Address 2 Register */ + + +/* Control register definitions --------------------------------------------------------------------------- */ +/*********************************************************************//** + * Macro defines for Command Register + **********************************************************************/ +#define EMAC_CR_RX_EN 0x00000001 /**< Enable Receive */ +#define EMAC_CR_TX_EN 0x00000002 /**< Enable Transmit */ +#define EMAC_CR_REG_RES 0x00000008 /**< Reset Host Registers */ +#define EMAC_CR_TX_RES 0x00000010 /**< Reset Transmit Datapath */ +#define EMAC_CR_RX_RES 0x00000020 /**< Reset Receive Datapath */ +#define EMAC_CR_PASS_RUNT_FRM 0x00000040 /**< Pass Runt Frames */ +#define EMAC_CR_PASS_RX_FILT 0x00000080 /**< Pass RX Filter */ +#define EMAC_CR_TX_FLOW_CTRL 0x00000100 /**< TX Flow Control */ +#define EMAC_CR_RMII 0x00000200 /**< Reduced MII Interface */ +#define EMAC_CR_FULL_DUP 0x00000400 /**< Full Duplex */ + +/*********************************************************************//** + * Macro defines for Status Register + **********************************************************************/ +#define EMAC_SR_RX_EN 0x00000001 /**< Enable Receive */ +#define EMAC_SR_TX_EN 0x00000002 /**< Enable Transmit */ + +/*********************************************************************//** + * Macro defines for Transmit Status Vector 0 Register + **********************************************************************/ +#define EMAC_TSV0_CRC_ERR 0x00000001 /**< CRC error */ +#define EMAC_TSV0_LEN_CHKERR 0x00000002 /**< Length Check Error */ +#define EMAC_TSV0_LEN_OUTRNG 0x00000004 /**< Length Out of Range */ +#define EMAC_TSV0_DONE 0x00000008 /**< Tramsmission Completed */ +#define EMAC_TSV0_MCAST 0x00000010 /**< Multicast Destination */ +#define EMAC_TSV0_BCAST 0x00000020 /**< Broadcast Destination */ +#define EMAC_TSV0_PKT_DEFER 0x00000040 /**< Packet Deferred */ +#define EMAC_TSV0_EXC_DEFER 0x00000080 /**< Excessive Packet Deferral */ +#define EMAC_TSV0_EXC_COLL 0x00000100 /**< Excessive Collision */ +#define EMAC_TSV0_LATE_COLL 0x00000200 /**< Late Collision Occured */ +#define EMAC_TSV0_GIANT 0x00000400 /**< Giant Frame */ +#define EMAC_TSV0_UNDERRUN 0x00000800 /**< Buffer Underrun */ +#define EMAC_TSV0_BYTES 0x0FFFF000 /**< Total Bytes Transferred */ +#define EMAC_TSV0_CTRL_FRAME 0x10000000 /**< Control Frame */ +#define EMAC_TSV0_PAUSE 0x20000000 /**< Pause Frame */ +#define EMAC_TSV0_BACK_PRESS 0x40000000 /**< Backpressure Method Applied */ +#define EMAC_TSV0_VLAN 0x80000000 /**< VLAN Frame */ + +/*********************************************************************//** + * Macro defines for Transmit Status Vector 1 Register + **********************************************************************/ +#define EMAC_TSV1_BYTE_CNT 0x0000FFFF /**< Transmit Byte Count */ +#define EMAC_TSV1_COLL_CNT 0x000F0000 /**< Transmit Collision Count */ + +/*********************************************************************//** + * Macro defines for Receive Status Vector Register + **********************************************************************/ +#define EMAC_RSV_BYTE_CNT 0x0000FFFF /**< Receive Byte Count */ +#define EMAC_RSV_PKT_IGNORED 0x00010000 /**< Packet Previously Ignored */ +#define EMAC_RSV_RXDV_SEEN 0x00020000 /**< RXDV Event Previously Seen */ +#define EMAC_RSV_CARR_SEEN 0x00040000 /**< Carrier Event Previously Seen */ +#define EMAC_RSV_REC_CODEV 0x00080000 /**< Receive Code Violation */ +#define EMAC_RSV_CRC_ERR 0x00100000 /**< CRC Error */ +#define EMAC_RSV_LEN_CHKERR 0x00200000 /**< Length Check Error */ +#define EMAC_RSV_LEN_OUTRNG 0x00400000 /**< Length Out of Range */ +#define EMAC_RSV_REC_OK 0x00800000 /**< Frame Received OK */ +#define EMAC_RSV_MCAST 0x01000000 /**< Multicast Frame */ +#define EMAC_RSV_BCAST 0x02000000 /**< Broadcast Frame */ +#define EMAC_RSV_DRIB_NIBB 0x04000000 /**< Dribble Nibble */ +#define EMAC_RSV_CTRL_FRAME 0x08000000 /**< Control Frame */ +#define EMAC_RSV_PAUSE 0x10000000 /**< Pause Frame */ +#define EMAC_RSV_UNSUPP_OPC 0x20000000 /**< Unsupported Opcode */ +#define EMAC_RSV_VLAN 0x40000000 /**< VLAN Frame */ + +/*********************************************************************//** + * Macro defines for Flow Control Counter Register + **********************************************************************/ +#define EMAC_FCC_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter */ +#define EMAC_FCC_PAUSE_TIM(n) ((n&0xFFFF)<<16) /**< Pause Timer */ + +/*********************************************************************//** + * Macro defines for Flow Control Status Register + **********************************************************************/ +#define EMAC_FCS_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter Current */ + + +/* Receive filter register definitions -------------------------------------------------------- */ +/*********************************************************************//** + * Macro defines for Receive Filter Control Register + **********************************************************************/ +#define EMAC_RFC_UCAST_EN 0x00000001 /**< Accept Unicast Frames Enable */ +#define EMAC_RFC_BCAST_EN 0x00000002 /**< Accept Broadcast Frames Enable */ +#define EMAC_RFC_MCAST_EN 0x00000004 /**< Accept Multicast Frames Enable */ +#define EMAC_RFC_UCAST_HASH_EN 0x00000008 /**< Accept Unicast Hash Filter Frames */ +#define EMAC_RFC_MCAST_HASH_EN 0x00000010 /**< Accept Multicast Hash Filter Fram.*/ +#define EMAC_RFC_PERFECT_EN 0x00000020 /**< Accept Perfect Match Enable */ +#define EMAC_RFC_MAGP_WOL_EN 0x00001000 /**< Magic Packet Filter WoL Enable */ +#define EMAC_RFC_PFILT_WOL_EN 0x00002000 /**< Perfect Filter WoL Enable */ + +/*********************************************************************//** + * Macro defines for Receive Filter WoL Status/Clear Registers + **********************************************************************/ +#define EMAC_WOL_UCAST 0x00000001 /**< Unicast Frame caused WoL */ +#define EMAC_WOL_BCAST 0x00000002 /**< Broadcast Frame caused WoL */ +#define EMAC_WOL_MCAST 0x00000004 /**< Multicast Frame caused WoL */ +#define EMAC_WOL_UCAST_HASH 0x00000008 /**< Unicast Hash Filter Frame WoL */ +#define EMAC_WOL_MCAST_HASH 0x00000010 /**< Multicast Hash Filter Frame WoL */ +#define EMAC_WOL_PERFECT 0x00000020 /**< Perfect Filter WoL */ +#define EMAC_WOL_RX_FILTER 0x00000080 /**< RX Filter caused WoL */ +#define EMAC_WOL_MAG_PACKET 0x00000100 /**< Magic Packet Filter caused WoL */ +#define EMAC_WOL_BITMASK 0x01BF /**< Receive Filter WoL Status/Clear bitmasl value */ + + +/* Module control register definitions ---------------------------------------------------- */ +/*********************************************************************//** + * Macro defines for Interrupt Status/Enable/Clear/Set Registers + **********************************************************************/ +#define EMAC_INT_RX_OVERRUN 0x00000001 /**< Overrun Error in RX Queue */ +#define EMAC_INT_RX_ERR 0x00000002 /**< Receive Error */ +#define EMAC_INT_RX_FIN 0x00000004 /**< RX Finished Process Descriptors */ +#define EMAC_INT_RX_DONE 0x00000008 /**< Receive Done */ +#define EMAC_INT_TX_UNDERRUN 0x00000010 /**< Transmit Underrun */ +#define EMAC_INT_TX_ERR 0x00000020 /**< Transmit Error */ +#define EMAC_INT_TX_FIN 0x00000040 /**< TX Finished Process Descriptors */ +#define EMAC_INT_TX_DONE 0x00000080 /**< Transmit Done */ +#define EMAC_INT_SOFT_INT 0x00001000 /**< Software Triggered Interrupt */ +#define EMAC_INT_WAKEUP 0x00002000 /**< Wakeup Event Interrupt */ + +/*********************************************************************//** + * Macro defines for Power Down Register + **********************************************************************/ +#define EMAC_PD_POWER_DOWN 0x80000000 /**< Power Down MAC */ + +/* Descriptor and status formats ---------------------------------------------------- */ +/*********************************************************************//** + * Macro defines for RX Descriptor Control Word + **********************************************************************/ +#define EMAC_RCTRL_SIZE(n) (n&0x7FF) /**< Buffer size field */ +#define EMAC_RCTRL_INT 0x80000000 /**< Generate RxDone Interrupt */ + +/*********************************************************************//** + * Macro defines for RX Status Hash CRC Word + **********************************************************************/ +#define EMAC_RHASH_SA 0x000001FF /**< Hash CRC for Source Address */ +#define EMAC_RHASH_DA 0x001FF000 /**< Hash CRC for Destination Address */ + +/*********************************************************************//** + * Macro defines for RX Status Information Word + **********************************************************************/ +#define EMAC_RINFO_SIZE 0x000007FF /**< Data size in bytes */ +#define EMAC_RINFO_CTRL_FRAME 0x00040000 /**< Control Frame */ +#define EMAC_RINFO_VLAN 0x00080000 /**< VLAN Frame */ +#define EMAC_RINFO_FAIL_FILT 0x00100000 /**< RX Filter Failed */ +#define EMAC_RINFO_MCAST 0x00200000 /**< Multicast Frame */ +#define EMAC_RINFO_BCAST 0x00400000 /**< Broadcast Frame */ +#define EMAC_RINFO_CRC_ERR 0x00800000 /**< CRC Error in Frame */ +#define EMAC_RINFO_SYM_ERR 0x01000000 /**< Symbol Error from PHY */ +#define EMAC_RINFO_LEN_ERR 0x02000000 /**< Length Error */ +#define EMAC_RINFO_RANGE_ERR 0x04000000 /**< Range Error (exceeded max. size) */ +#define EMAC_RINFO_ALIGN_ERR 0x08000000 /**< Alignment Error */ +#define EMAC_RINFO_OVERRUN 0x10000000 /**< Receive overrun */ +#define EMAC_RINFO_NO_DESCR 0x20000000 /**< No new Descriptor available */ +#define EMAC_RINFO_LAST_FLAG 0x40000000 /**< Last Fragment in Frame */ +#define EMAC_RINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */ +#define EMAC_RINFO_ERR_MASK (EMAC_RINFO_FAIL_FILT | EMAC_RINFO_CRC_ERR | EMAC_RINFO_SYM_ERR | \ +EMAC_RINFO_LEN_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_OVERRUN) + +/*********************************************************************//** + * Macro defines for TX Descriptor Control Word + **********************************************************************/ +#define EMAC_TCTRL_SIZE 0x000007FF /**< Size of data buffer in bytes */ +#define EMAC_TCTRL_OVERRIDE 0x04000000 /**< Override Default MAC Registers */ +#define EMAC_TCTRL_HUGE 0x08000000 /**< Enable Huge Frame */ +#define EMAC_TCTRL_PAD 0x10000000 /**< Pad short Frames to 64 bytes */ +#define EMAC_TCTRL_CRC 0x20000000 /**< Append a hardware CRC to Frame */ +#define EMAC_TCTRL_LAST 0x40000000 /**< Last Descriptor for TX Frame */ +#define EMAC_TCTRL_INT 0x80000000 /**< Generate TxDone Interrupt */ + +/*********************************************************************//** + * Macro defines for TX Status Information Word + **********************************************************************/ +#define EMAC_TINFO_COL_CNT 0x01E00000 /**< Collision Count */ +#define EMAC_TINFO_DEFER 0x02000000 /**< Packet Deferred (not an error) */ +#define EMAC_TINFO_EXCESS_DEF 0x04000000 /**< Excessive Deferral */ +#define EMAC_TINFO_EXCESS_COL 0x08000000 /**< Excessive Collision */ +#define EMAC_TINFO_LATE_COL 0x10000000 /**< Late Collision Occured */ +#define EMAC_TINFO_UNDERRUN 0x20000000 /**< Transmit Underrun */ +#define EMAC_TINFO_NO_DESCR 0x40000000 /**< No new Descriptor available */ +#define EMAC_TINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */ + +#ifdef MCB_LPC_1768 +/* DP83848C PHY definition ------------------------------------------------------------ */ + +/** PHY device reset time out definition */ +#define EMAC_PHY_RESP_TOUT 0x100000UL + +/* ENET Device Revision ID */ +#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */ + +/*********************************************************************//** + * Macro defines for DP83848C PHY Registers + **********************************************************************/ +#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */ +#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */ +#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */ +#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */ +#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */ +#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */ +#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */ +#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */ +#define EMAC_PHY_REG_LPNPA 0x08 + +/*********************************************************************//** + * Macro defines for PHY Extended Registers + **********************************************************************/ +#define EMAC_PHY_REG_STS 0x10 /**< Status Register */ +#define EMAC_PHY_REG_MICR 0x11 /**< MII Interrupt Control Register */ +#define EMAC_PHY_REG_MISR 0x12 /**< MII Interrupt Status Register */ +#define EMAC_PHY_REG_FCSCR 0x14 /**< False Carrier Sense Counter */ +#define EMAC_PHY_REG_RECR 0x15 /**< Receive Error Counter */ +#define EMAC_PHY_REG_PCSR 0x16 /**< PCS Sublayer Config. and Status */ +#define EMAC_PHY_REG_RBR 0x17 /**< RMII and Bypass Register */ +#define EMAC_PHY_REG_LEDCR 0x18 /**< LED Direct Control Register */ +#define EMAC_PHY_REG_PHYCR 0x19 /**< PHY Control Register */ +#define EMAC_PHY_REG_10BTSCR 0x1A /**< 10Base-T Status/Control Register */ +#define EMAC_PHY_REG_CDCTRL1 0x1B /**< CD Test Control and BIST Extens. */ +#define EMAC_PHY_REG_EDCR 0x1D /**< Energy Detect Control Register */ + +/*********************************************************************//** + * Macro defines for PHY Basic Mode Control Register + **********************************************************************/ +#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */ +#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */ +#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */ +#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */ +#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */ +#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */ +#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */ +#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */ + +/*********************************************************************//** + * Macro defines for PHY Basic Mode Status Status Register + **********************************************************************/ +#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */ +#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */ +#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */ +#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */ +#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */ +#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */ +#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */ +#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */ +#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */ +#define EMAC_PHY_BMSR_LINK_ESTABLISHED (1<<2) /**< Link status */ + +/*********************************************************************//** + * Macro defines for PHY Status Register + **********************************************************************/ +#define EMAC_PHY_SR_REMOTE_FAULT (1<<6) /**< Remote Fault */ +#define EMAC_PHY_SR_JABBER (1<<5) /**< Jabber detect */ +#define EMAC_PHY_SR_AUTO_DONE (1<<4) /**< Auto Negotiation complete */ +#define EMAC_PHY_SR_LOOPBACK (1<<3) /**< Loop back status */ +#define EMAC_PHY_SR_DUP (1<<2) /**< Duplex status */ +#define EMAC_PHY_SR_SPEED (1<<1) /**< Speed status */ +#define EMAC_PHY_SR_LINK (1<<0) /**< Link Status */ + +#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */ +#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */ +#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */ +#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */ +#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */ + +#define EMAC_DEF_ADR 0x0100 /**< Default PHY device address */ +#define EMAC_DP83848C_ID 0x20005C90 /**< PHY Identifier */ + +#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13)) +#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12)) +#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */ + +#elif defined(IAR_LPC_1768) +/* KSZ8721BL PHY definition ------------------------------------------------------------ */ +/** PHY device reset time out definition */ +#define EMAC_PHY_RESP_TOUT 0x100000UL + +/* ENET Device Revision ID */ +#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */ + +/*********************************************************************//** + * Macro defines for KSZ8721BL PHY Registers + **********************************************************************/ +#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */ +#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */ +#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */ +#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */ +#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */ +#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */ +#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */ +#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */ +#define EMAC_PHY_REG_LPNPA 0x08 /**< Link Partner Next Page Ability */ +#define EMAC_PHY_REG_REC 0x15 /**< RXError Counter Register */ +#define EMAC_PHY_REG_ISC 0x1b /**< Interrupt Control/Status Register */ +#define EMAC_PHY_REG_100BASE 0x1f /**< 100BASE-TX PHY Control Register */ + +/*********************************************************************//** + * Macro defines for PHY Basic Mode Control Register + **********************************************************************/ +#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */ +#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */ +#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */ +#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */ +#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */ +#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */ +#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */ +#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */ +#define EMAC_PHY_BMCR_COLLISION (1<<7) /**< Collision test */ +#define EMAC_PHY_BMCR_TXDIS (1<<0) /**< Disable transmit */ + +/*********************************************************************//** + * Macro defines for PHY Basic Mode Status Register + **********************************************************************/ +#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */ +#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */ +#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */ +#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */ +#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */ +#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */ +#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */ +#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */ +#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */ +#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */ +#define EMAC_PHY_BMSR_JABBER_DETECT (1<<1) /**< Jabber detect */ +#define EMAC_PHY_BMSR_EXTEND (1<<0) /**< Extended support */ + +/*********************************************************************//** + * Macro defines for PHY Identifier + **********************************************************************/ +/* PHY Identifier 1 bitmap definitions */ +#define EMAC_PHY_IDR1(n) (n & 0xFFFF) /**< PHY ID1 Number */ + +/* PHY Identifier 2 bitmap definitions */ +#define EMAC_PHY_IDR2(n) (n & 0xFFFF) /**< PHY ID2 Number */ + +/*********************************************************************//** + * Macro defines for Auto-Negotiation Advertisement + **********************************************************************/ +#define EMAC_PHY_AN_NEXTPAGE (1<<15) /**< Next page capable */ +#define EMAC_PHY_AN_REMOTE_FAULT (1<<13) /**< Remote Fault support */ +#define EMAC_PHY_AN_PAUSE (1<<10) /**< Pause support */ +#define EMAC_PHY_AN_100BASE_T4 (1<<9) /**< T4 capable */ +#define EMAC_PHY_AN_100BASE_TX_FD (1<<8) /**< TX with Full-duplex capable */ +#define EMAC_PHY_AN_100BASE_TX (1<<7) /**< TX capable */ +#define EMAC_PHY_AN_10BASE_T_FD (1<<6) /**< 10Mbps with full-duplex capable */ +#define EMAC_PHY_AN_10BASE_T (1<<5) /**< 10Mbps capable */ +#define EMAC_PHY_AN_FIELD(n) (n & 0x1F) /**< Selector Field */ + +#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */ +#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */ +#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */ +#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */ +#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */ + +#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13)) +#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12)) + +#define EMAC_DEF_ADR (0x01<<8) /**< Default PHY device address */ +#define EMAC_KSZ8721BL_ID ((0x22 << 16) | 0x1619 ) /**< PHY Identifier */ +#endif + +/** + * @} + */ + + +/* Public Types --------------------------------------------------------------- */ +/** @defgroup EMAC_Public_Types EMAC Public Types + * @{ + */ + +/* Descriptor and status formats ---------------------------------------------- */ + +/** + * @brief RX Descriptor structure type definition + */ +typedef struct { + uint32_t Packet; /**< Receive Packet Descriptor */ + uint32_t Ctrl; /**< Receive Control Descriptor */ +} RX_Desc; + +/** + * @brief RX Status structure type definition + */ +typedef struct { + uint32_t Info; /**< Receive Information Status */ + uint32_t HashCRC; /**< Receive Hash CRC Status */ +} RX_Stat; + +/** + * @brief TX Descriptor structure type definition + */ +typedef struct { + uint32_t Packet; /**< Transmit Packet Descriptor */ + uint32_t Ctrl; /**< Transmit Control Descriptor */ +} TX_Desc; + +/** + * @brief TX Status structure type definition + */ +typedef struct { + uint32_t Info; /**< Transmit Information Status */ +} TX_Stat; + + +/** + * @brief TX Data Buffer structure definition + */ +typedef struct { + uint32_t ulDataLen; /**< Data length */ + uint32_t *pbDataBuf; /**< A word-align data pointer to data buffer */ +} EMAC_PACKETBUF_Type; + +/** + * @brief EMAC configuration structure definition + */ +typedef struct { + uint32_t Mode; /**< Supported EMAC PHY device speed, should be one of the following: + - EMAC_MODE_AUTO + - EMAC_MODE_10M_FULL + - EMAC_MODE_10M_HALF + - EMAC_MODE_100M_FULL + - EMAC_MODE_100M_HALF + */ + uint8_t *pbEMAC_Addr; /**< Pointer to EMAC Station address that contains 6-bytes + of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5]) + */ +} EMAC_CFG_Type; + +/** Ethernet block power/clock control bit*/ +#define CLKPWR_PCONP_PCENET ((uint32_t)(1<<30)) + +#ifdef __cplusplus +} +#endif + +#endif /* LPC17XX_EMAC_H_ */ + +/** + * @} + */ + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h new file mode 100644 index 0000000..43efb8a --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h @@ -0,0 +1,104 @@ +/********************************************************************** +* $Id$ lpc_emac_config.h 2011-11-20 +*//** +* @file lpc_emac_config.h +* @brief PHY and EMAC configuration file +* @version 1.0 +* @date 20 Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __LPC_EMAC_CONFIG_H +#define __LPC_EMAC_CONFIG_H + +#define LPC17_ETH_IF_NAME "lpc" +#define LPC17_ETH_HWADDR_SIZE 6 + +#define DEFAULT_THREAD_STACKSIZE 512 + +/** @defgroup lwip_phy_config PHY configuration + * @ingroup lwip_phy + * + * Configuration options for the PHY connected to the LPC EMAC. + * @{ + */ + +/** \brief The PHY address connected the to MII/RMII + */ +#define LPC_PHYDEF_PHYADDR 1 /**< The PHY address on the PHY device. */ + +/** \brief Enable autonegotiation mode. + * If this is enabled, the PHY will attempt to auto-negotiate the + * best link mode if the PHY supports it. If this is not enabled, + * the PHY_USE_FULL_DUPLEX and PHY_USE_100MBS defines will be + * used to select the link mode. Note that auto-negotiation may + * take a few seconds to complete. + */ +#define PHY_USE_AUTONEG 1 /**< Enables auto-negotiation mode. */ + +/** \brief Sets up the PHY interface to either full duplex operation or + * half duplex operation if PHY_USE_AUTONEG is not enabled. + */ +#define PHY_USE_FULL_DUPLEX 1 /**< Sets duplex mode to full. */ + +/** \brief Sets up the PHY interface to either 100MBS operation or 10MBS + * operation if PHY_USE_AUTONEG is not enabled. + */ +#define PHY_USE_100MBS 1 /**< Sets data rate to 100Mbps. */ + +/** + * @} + */ + +/** @defgroup emac_config EMAC configuration + * + * Configuration options for the LPC EMAC. + * @{ + */ + +/** \brief Selects RMII or MII connection type in the EMAC peripheral + */ +#define LPC_EMAC_RMII 1 /**< Use the RMII or MII driver variant .*/ + +/** \brief Defines the number of descriptors used for RX. This + * must be a minimum value of 2. + */ +#define LPC_NUM_BUFF_RXDESCS 4 + +/** \brief Defines the number of descriptors used for TX. Must + * be a minimum value of 2. + */ +#define LPC_NUM_BUFF_TXDESCS 9 + +/** \brief Set this define to 1 to enable bounce buffers for transmit memory + * buffers that cannot be sent via the zero-copy method. Some chained + * buffers may have a payload address that links to an area of memory that + * cannot be used for transmit DMA operations. If this define is + * set to 1, an extra check will be made with the buffers. If a buffer + * is determined to be non-usable for zero-copy, a temporary bounce + * buffer will be created and used instead. + */ +#define LPC_TX_PBUF_BOUNCE_EN 1 + +/** + * @} + */ + +#endif /* __LPC_EMAC_CONFIG_H */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h new file mode 100644 index 0000000..5c2f314 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h @@ -0,0 +1,140 @@ +/********************************************************************** +* $Id$ lpc_phy.h 2011-11-20 +*//** +* @file lpc_phy.h +* @brief Common PHY definitions used with all PHYs +* @version 1.0 +* @date 20 Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#ifndef __LPC_PHY_H_ +#define __LPC_PHY_H_ + +/* These PHY functions are usually part of the EMAC driver */ + +/** \brief Phy status update state machine + * + * This function provides a state machine for maintaining the PHY + * status without blocking. It must be occasionally called for the + * PHY status to be maintained. + * + * \param[in] lpc17_emac LPC17 EMAC + */ + +int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac); + +/** \brief Initialize the PHY + * + * This function initializes the PHY. It will block until complete. + * This function is called as part of the EMAC driver + * initialization. Configuration of the PHY at startup is + * controlled by setting up configuration defines in lpc_phy.h. + * + * \param[in] lpc17_emac LPC17 EMAC + * \param[in] rmii If set, configures the PHY for RMII mode + * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT + */ +bool lpc_phy_init(LPC17_EMAC *lpc17_emac, int rmii); + +/** \brief Write a value via the MII link (non-blocking) + * + * This function will write a value on the MII link interface to a PHY + * or a connected device. The function will return immediately without + * a status. Status needs to be polled later to determine if the write + * was successful. + * + * \param[in] PhyReg PHY register to write to + * \param[in] Value Value to write + */ +void lpc_mii_write_noblock(uint32_t PhyReg, uint32_t Value); + +/** \brief Write a value via the MII link (blocking) + * + * This function will write a value on the MII link interface to a PHY + * or a connected device. The function will block until complete. + * + * \param[in] PhyReg PHY register to write to + * \param[in] Value Value to write + * \returns 0 if the write was successful, otherwise !0 + */ +bool lpc_mii_write(uint32_t PhyReg, uint32_t Value); + +/** \brief Reads current MII link busy status + * + * This function will return the current MII link busy status and is meant to + * be used with non-blocking functions for monitor PHY status such as + * connection state. + * + * \returns !0 if the MII link is busy, otherwise 0 + */ +uint32_t lpc_mii_is_busy(void); + +/** \brief Starts a read operation via the MII link (non-blocking) + * + * This function returns the current value in the MII data register. It is + * meant to be used with the non-blocking oeprations. This value should + * only be read after a non-block read command has been issued and the + * MII status has been determined to be good. + * + * \returns The current value in the MII value register + */ +uint32_t lpc_mii_read_data(void); + +/** \brief Starts a read operation via the MII link (non-blocking) + * + * This function will start a read operation on the MII link interface + * from a PHY or a connected device. The function will not block and + * the status mist be polled until complete. Once complete, the data + * can be read. + * + * \param[in] PhyReg PHY register to read from + * \param[in] data Pointer to where to save data read via MII + * \returns 0 if the read was successful, otherwise !0 + * + */ +bool lpc_mii_read(uint32_t PhyReg, uint32_t *data); + +/** \brief Read a value via the MII link (blocking) + * + * This function will read a value on the MII link interface from a PHY + * or a connected device. The function will block until complete. + * + * \param[in] PhyReg PHY register to read from + */ +void lpc_mii_read_noblock(uint32_t PhyReg); + +/** + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated duplex mode. + * + * @param[in] full_duplex 0 = half duplex, 1 = full duplex + */ +void lpc_emac_set_duplex(int full_duplex); + +/** + * This function provides a method for the PHY to setup the EMAC + * for the PHY negotiated bit rate. + * + * @param[in] mbs_100 0 = 10mbs mode, 1 = 100mbs mode + */ +void lpc_emac_set_speed(int mbs_100); + +#endif /* __LPC_PHY_H_ */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp new file mode 100644 index 0000000..3cc40d3 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp @@ -0,0 +1,433 @@ +/********************************************************************** +* $Id$ lpc_phy_dp83848.c 2011-11-20 +*//** +* @file lpc_phy_dp83848.c +* @brief DP83848C PHY status and control. +* @version 1.0 +* @date 20 Nov. 2011 +* @author NXP MCU SW Application Team +* +* Copyright(C) 2011, NXP Semiconductor +* All rights reserved. +* +*********************************************************************** +* Software that is described herein is for illustrative purposes only +* which provides customers with programming information regarding the +* products. This software is supplied "AS IS" without any warranties. +* NXP Semiconductors assumes no responsibility or liability for the +* use of the software, conveys no license or title under any patent, +* copyright, or mask work right to the product. NXP Semiconductors +* reserves the right to make changes in the software without +* notification. NXP Semiconductors also make no representation or +* warranty that such application will be suitable for the specified +* use without further testing or modification. +**********************************************************************/ + +#include "netsocket/nsapi_types.h" +#include "lpc_emac_config.h" +#include "lpc17_emac.h" +#include "lpc_phy.h" +#include "lpc17xx_emac.h" + + +/** @defgroup dp83848_phy PHY status and control for the DP83848. + * @ingroup lwip_phy + * + * Various functions for controlling and monitoring the status of the + * DP83848 PHY. In polled (standalone) systems, the PHY state must be + * monitored as part of the application. In a threaded (RTOS) system, + * the PHY state is monitored by the PHY handler thread. The MAC + * driver will not transmit unless the PHY link is active. + * @{ + */ + +/** \brief DP83848 PHY register offsets */ +#define DP8_BMCR_REG 0x0 /**< Basic Mode Control Register */ +#define DP8_BMSR_REG 0x1 /**< Basic Mode Status Reg */ +#define DP8_IDR1_REG 0x2 /**< Basic Mode Status Reg */ +#define DP8_IDR2_REG 0x3 /**< Basic Mode Status Reg */ +#define DP8_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */ +#define DP8_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */ +#define DP8_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */ +#define DP8_PHY_STAT_REG 0x10 /**< PHY Status Register */ +#define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */ +#define DP8_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */ +#define DP8_PHY_STS_REG 0x19 /**< PHY Status Register */ + +#define DP8_PHY_SCSR_REG 0x1f /**< PHY Special Control/Status Register (LAN8720) */ + +/** \brief DP83848 Control register definitions */ +#define DP8_RESET (1 << 15) /**< 1= S/W Reset */ +#define DP8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */ +#define DP8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */ +#define DP8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */ +#define DP8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */ +#define DP8_ISOLATE (1 << 10) /**< 1=Isolate PHY */ +#define DP8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */ +#define DP8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */ +#define DP8_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */ + +/** \brief DP83848 Status register definitions */ +#define DP8_100BASE_T4 (1 << 15) /**< T4 mode */ +#define DP8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */ +#define DP8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */ +#define DP8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */ +#define DP8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */ +#define DP8_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */ +#define DP8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */ +#define DP8_RMT_FAULT (1 << 4) /**< Fault */ +#define DP8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */ +#define DP8_LINK_STATUS (1 << 2) /**< 1=Link active */ +#define DP8_JABBER_DETECT (1 << 1) /**< Jabber detect */ +#define DP8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */ + +/** \brief DP83848 PHY RBR MII dode definitions */ +#define DP8_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */ + +/** \brief DP83848 PHY status definitions */ +#define DP8_REMOTEFAULT (1 << 6) /**< Remote fault */ +#define DP8_FULLDUPLEX (1 << 2) /**< 1=full duplex */ +#define DP8_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */ +#define DP8_VALID_LINK (1 << 0) /**< 1=Link active */ + +/** \brief DP83848 PHY ID register definitions */ +#define DP8_PHYID1_OUI 0x2000 /**< Expected PHY ID1 */ +#define DP8_PHYID2_OUI 0x5c90 /**< Expected PHY ID2 */ + +/** \brief LAN8720 PHY Special Control/Status Register */ +#define PHY_SCSR_100MBIT 0x0008 /**< Speed: 1=100 MBit, 0=10Mbit */ +#define PHY_SCSR_DUPLEX 0x0010 /**< PHY Duplex Mask */ + +/** \brief Link status bits */ +#define LNK_STAT_VALID 0x01 +#define LNK_STAT_FULLDUPLEX 0x02 +#define LNK_STAT_SPEED10MPS 0x04 + +/** \brief PHY ID definitions */ +#define DP83848C_ID 0x20005C90 /**< PHY Identifier - DP83848C */ +#define LAN8720_ID 0x0007C0F0 /**< PHY Identifier - LAN8720 */ +#define KSZ8041_ID 0x00221510 /**< PHY Identifier - KSZ8041 */ + + +/** \brief PHY status structure used to indicate current status of PHY. + */ +typedef struct { + unsigned int phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */ + unsigned int phy_full_duplex:1; /**< Half/full duplex connection speed flag. */ + unsigned int phy_link_active:1; /**< Phy link active flag. */ +} PHY_STATUS_TYPE; + +/** \brief PHY update flags */ +static PHY_STATUS_TYPE physts; + +/** \brief Last PHY update flags, used for determing if something has changed */ +static PHY_STATUS_TYPE olddphysts; + +/** \brief PHY update counter for state machine */ +static int32_t phyustate; + +/** \brief Holds the PHY ID */ +static uint32_t phy_id; + +/** \brief Temporary holder of link status for LAN7420 */ +static uint32_t phy_lan7420_sts_tmp; + +/* Write a value via the MII link (non-blocking) */ +void lpc_mii_write_noblock(uint32_t PhyReg, uint32_t Value) +{ + /* Write value at PHY address and register */ + LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg; + LPC_EMAC->MWTD = Value; +} + +/* Write a value via the MII link (blocking) */ +bool lpc_mii_write(uint32_t PhyReg, uint32_t Value) +{ + uint32_t mst = 250; + int8_t sts = 0; + + /* Write value at PHY address and register */ + lpc_mii_write_noblock(PhyReg, Value); + + /* Wait for unbusy status */ + while (mst > 0) { + sts = LPC_EMAC->MIND; + if ((sts & EMAC_MIND_BUSY) == 0) + mst = 0; + else { + mst--; + osDelay(1); + } + } + + if (sts != 0) + return false; + + return true; +} + +/* Reads current MII link busy status */ +uint32_t lpc_mii_is_busy(void) +{ + return (uint32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY); +} + +/* Starts a read operation via the MII link (non-blocking) */ +uint32_t lpc_mii_read_data(void) +{ + uint32_t data = LPC_EMAC->MRDD; + LPC_EMAC->MCMD = 0; + + return data; +} + +/* Starts a read operation via the MII link (non-blocking) */ +void lpc_mii_read_noblock(uint32_t PhyReg) +{ + /* Read value at PHY address and register */ + LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg; + LPC_EMAC->MCMD = EMAC_MCMD_READ; +} + +/* Read a value via the MII link (blocking) */ +bool lpc_mii_read(uint32_t PhyReg, uint32_t *data) +{ + uint32_t mst = 250; + int8_t sts = 0; + + /* Read value at PHY address and register */ + lpc_mii_read_noblock(PhyReg); + + /* Wait for unbusy status */ + while (mst > 0) { + sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL; + if ((sts & EMAC_MIND_BUSY) == 0) { + mst = 0; + *data = LPC_EMAC->MRDD; + } else { + mst--; + osDelay(1); + } + } + + LPC_EMAC->MCMD = 0; + + if (sts != 0) + return false; + + return true; +} + +/** \brief Update PHY status from passed value + * + * This function updates the current PHY status based on the + * passed PHY status word. The PHY status indicate if the link + * is active, the connection speed, and duplex. + * + * \param[in] lpc17_emac LPC17 EMAC + * \param[in] linksts Status word from PHY + * \return 1 if the status has changed, otherwise 0 + */ +static int32_t lpc_update_phy_sts(LPC17_EMAC *lpc17_emac, uint32_t linksts) +{ + int32_t changed = 0; + + /* Update link active status */ + if (linksts & LNK_STAT_VALID) + physts.phy_link_active = 1; + else + physts.phy_link_active = 0; + + /* Full or half duplex */ + if (linksts & LNK_STAT_FULLDUPLEX) + physts.phy_full_duplex = 1; + else + physts.phy_full_duplex = 0; + + /* Configure 100MBit/10MBit mode. */ + if (linksts & LNK_STAT_SPEED10MPS) + physts.phy_speed_100mbs = 0; + else + physts.phy_speed_100mbs = 1; + + if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) { + changed = 1; + if (physts.phy_speed_100mbs) { + /* 100MBit mode. */ + lpc_emac_set_speed(1); + } + else { + /* 10MBit mode. */ + lpc_emac_set_speed(0); + } + + olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs; + } + + if (physts.phy_full_duplex != olddphysts.phy_full_duplex) { + changed = 1; + if (physts.phy_full_duplex) + lpc_emac_set_duplex(1); + else + lpc_emac_set_duplex(0); + + olddphysts.phy_full_duplex = physts.phy_full_duplex; + } + + if (physts.phy_link_active != olddphysts.phy_link_active) { + changed = 1; + + if (physts.phy_link_active) { + lpc17_emac->update_link_status(true); + } else { + lpc17_emac->update_link_status(false); + } + + olddphysts.phy_link_active = physts.phy_link_active; + } + + return changed; +} + +/** \brief Initialize the DP83848 PHY. + * + * This function initializes the DP83848 PHY. It will block until + * complete. This function is called as part of the EMAC driver + * initialization. Configuration of the PHY at startup is + * controlled by setting up configuration defines in lpc_phy.h. + * + * \param[in] lpc17_emac LPC17 EMAC + * \param[in] rmii If set, configures the PHY for RMII mode + * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT + */ +bool lpc_phy_init(LPC17_EMAC *lpc17_emac, int rmii) +{ + uint32_t tmp; + int32_t i; + + physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0; + physts.phy_full_duplex = olddphysts.phy_full_duplex = 0; + physts.phy_link_active = olddphysts.phy_link_active = 0; + phyustate = 0; + + /* Only first read and write are checked for failure */ + /* Put the DP83848C in reset mode and wait for completion */ + if (!lpc_mii_write(DP8_BMCR_REG, DP8_RESET)) { + return false; + } + i = 400; + while (i > 0) { + osDelay(1); /* 1 ms */ + if (!lpc_mii_read(DP8_BMCR_REG, &tmp)) + return false; + + if (!(tmp & (DP8_RESET | DP8_POWER_DOWN))) + i = -1; + else + i--; + } + /* Timeout? */ + if (i == 0) + return false; + + // read PHY ID + lpc_mii_read(DP8_IDR1_REG, &tmp); + phy_id = (tmp << 16); + lpc_mii_read(DP8_IDR2_REG, &tmp); + phy_id |= (tmp & 0XFFF0); + + /* Setup link based on configuration options */ +#if PHY_USE_AUTONEG==1 + tmp = DP8_AUTONEG; +#else + tmp = 0; +#endif +#if PHY_USE_100MBS==1 + tmp |= DP8_SPEED_SELECT; +#endif +#if PHY_USE_FULL_DUPLEX==1 + tmp |= DP8_DUPLEX_MODE; +#endif + lpc_mii_write(DP8_BMCR_REG, tmp); + + /* Enable RMII mode for PHY */ + if (rmii) { + /* Mode is set with config pins on KSZ8041 */ + if (phy_id != KSZ8041_ID) + lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE); + } + /* The link is not set active at this point, but will be detected + later */ + + return true; +} + +/** \brief Phy status update state machine + * + * \param[in] lpc17_emac LPC17 EMAC + * \return 1 if the status has changed, otherwise 0 + */ +int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac) +{ + int32_t changed = 0; + uint32_t data = 0; + uint32_t tmp; + + switch (phyustate) { + default: + case 0: + if (phy_id == DP83848C_ID) { + lpc_mii_read_noblock(DP8_PHY_STAT_REG); + phyustate = 2; + } + else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { + lpc_mii_read_noblock(DP8_PHY_SCSR_REG); + phyustate = 1; + } + break; + + case 1: + if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { + tmp = lpc_mii_read_data(); + // we get speed and duplex here. + phy_lan7420_sts_tmp = (tmp & PHY_SCSR_DUPLEX) ? LNK_STAT_FULLDUPLEX : 0; + phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS; + + //read the status register to get link status + lpc_mii_read_noblock(DP8_BMSR_REG); + phyustate = 2; + } + break; + + case 2: + /* Wait for read status state */ + if (!lpc_mii_is_busy()) { + /* Update PHY status */ + tmp = lpc_mii_read_data(); + + if (phy_id == DP83848C_ID) { + // STS register contains all needed status bits + data = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0; + data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0; + data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0; + } + else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { + // we only get the link status here. + phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0; + data = phy_lan7420_sts_tmp; + } + + changed = lpc_update_phy_sts(lpc17_emac, data); + phyustate = 0; + } + break; + } + + return changed; +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c new file mode 100644 index 0000000..096689e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c @@ -0,0 +1,227 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsl_iocon.h" + +#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ +#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ +#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */ +#define IOCON_PIO_FUNC6 0x06u /*!<@brief Selects pin function 6 */ +#define IOCON_PIO_FUNC7 0x07u /*!<@brief Selects pin function 7 */ +#define IOCON_PIO_INPFILT_OFF 0x0200u /*!<@brief Input filter disabled */ +#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ +#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */ +#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ +#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ +#define IOCON_PIO_SLEW_FAST 0x0400u /*!<@brief Fast mode, slew rate control is disabled */ +#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ + +/******************************************************************************* + * Code + ******************************************************************************/ +void lpc546xx_init_eth_hardware(void) +{ + CLOCK_EnableClock(kCLOCK_InputMux); + + /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */ + CLOCK_EnableClock(kCLOCK_Iocon); + + const uint32_t port0_pin10_config = (/* Pin is configured as SWO */ + IOCON_PIO_FUNC6 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN10 (coords: P2) is configured as SWO */ + IOCON_PinMuxSet(IOCON, 0U, 10U, port0_pin10_config); + + const uint32_t port1_pin10_config = (/* Pin is configured as ENET_TXD1 */ + IOCON_PIO_FUNC1 /* IOCON_PIO_FUNC1 */ | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN10 (coords: E14) is configured as ENET_TXD1 */ + IOCON_PinMuxSet(IOCON, 1U, 10U, port1_pin10_config); + + + const uint32_t port1_pin18_config = (/* Pin is configured as ENET_PHY_RST */ + IOCON_PIO_FUNC0 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN18 (coords: H11) is configured as ENET_PHY_RST */ + IOCON_PinMuxSet(IOCON, 1U, 18U, port1_pin18_config); + + const uint32_t port1_pin14_config = (/* Pin is configured as ENET_RX_DV */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN14 (coords: B9) is configured as ENET_RX_DV */ + IOCON_PinMuxSet(IOCON, 1U, 14U, port1_pin14_config); + + const uint32_t port1_pin12_config = (/* Pin is configured as ENET_RXD0 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT1 PIN12 (coords: A9) is configured as ENET_RXD0 */ + IOCON_PinMuxSet(IOCON, 1U, 12U, port1_pin12_config); + + const uint32_t port1_pin13_config = (/* Pin is configured as ENET_RXD1 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */ + IOCON_PinMuxSet(IOCON, 1U, 13U, port1_pin13_config); + + const uint32_t port1_pin11_config = (/* Pin is configured as ENET_TX_EN */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */ + IOCON_PinMuxSet(IOCON, 1U, 11U, port1_pin11_config); + + const uint32_t port1_pin15_config = (/* Pin is configured as ENET_RX_CLK */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */ + IOCON_PinMuxSet(IOCON, 1U, 15U, port1_pin15_config); + + const uint32_t port1_pin16_config = (/* Pin is configured as ENET_MDC */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */ + IOCON_PinMuxSet(IOCON, 1U, 16U, port1_pin16_config); + + const uint32_t port1_pin17_config = (/* Pin is configured as ENET_MDIO */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */ + IOCON_PinMuxSet(IOCON, 1U, 17U, port1_pin17_config); + + const uint32_t port1_pin9_config = (/* Pin is configured as ENET_TXD0 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */ + IOCON_PinMuxSet(IOCON, 1U, 9U, port1_pin9_config); +} diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c new file mode 100644 index 0000000..22836f9 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c @@ -0,0 +1,261 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "fsl_iocon.h" + +#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ +#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ +#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */ +#define IOCON_PIO_FUNC6 0x06u /*!<@brief Selects pin function 6 */ +#define IOCON_PIO_FUNC7 0x07u /*!<@brief Selects pin function 7 */ +#define IOCON_PIO_INPFILT_OFF 0x0200u /*!<@brief Input filter disabled */ +#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ +#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */ +#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ +#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ +#define IOCON_PIO_SLEW_FAST 0x0400u /*!<@brief Fast mode, slew rate control is disabled */ +#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ + +/******************************************************************************* + * Code + ******************************************************************************/ +void lpc546xx_init_eth_hardware(void) +{ + CLOCK_EnableClock(kCLOCK_InputMux); + + /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */ + CLOCK_EnableClock(kCLOCK_Iocon); + + const uint32_t port0_pin10_config = (/* Pin is configured as SWO */ + IOCON_PIO_FUNC6 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN10 (coords: P2) is configured as SWO */ + IOCON_PinMuxSet(IOCON, 0U, 10U, port0_pin10_config); + + const uint32_t port0_pin17_config = (/* Pin is configured as ENET_TXD1 */ + IOCON_PIO_FUNC7 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN17 (coords: E14) is configured as ENET_TXD1 */ + IOCON_PinMuxSet(IOCON, 0U, 17U, port0_pin17_config); + + const uint32_t port0_pin29_config = (/* Pin is configured as FC0_RXD_SDA_MOSI */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Fast mode, slew rate control is disabled */ + IOCON_PIO_SLEW_FAST | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN29 (coords: B13) is configured as FC0_RXD_SDA_MOSI */ + IOCON_PinMuxSet(IOCON, 0U, 29U, port0_pin29_config); + + const uint32_t port0_pin30_config = (/* Pin is configured as FC0_TXD_SCL_MISO */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Fast mode, slew rate control is disabled */ + IOCON_PIO_SLEW_FAST | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT0 PIN30 (coords: A2) is configured as FC0_TXD_SCL_MISO */ + IOCON_PinMuxSet(IOCON, 0U, 30U, port0_pin30_config); + + const uint32_t port2_pin26_config = (/* Pin is configured as PIO2_26 */ + IOCON_PIO_FUNC0 | + /* Selects pull-up function */ + IOCON_PIO_MODE_PULLUP | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT2 PIN26 (coords: H11) is configured as PIO2_26 */ + IOCON_PinMuxSet(IOCON, 2U, 26U, port2_pin26_config); + + const uint32_t port4_pin10_config = (/* Pin is configured as ENET_RX_DV */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN10 (coords: B9) is configured as ENET_RX_DV */ + IOCON_PinMuxSet(IOCON, 4U, 10U, port4_pin10_config); + + const uint32_t port4_pin11_config = (/* Pin is configured as ENET_RXD0 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN11 (coords: A9) is configured as ENET_RXD0 */ + IOCON_PinMuxSet(IOCON, 4U, 11U, port4_pin11_config); + + const uint32_t port4_pin12_config = (/* Pin is configured as ENET_RXD1 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */ + IOCON_PinMuxSet(IOCON, 4U, 12U, port4_pin12_config); + + const uint32_t port4_pin13_config = (/* Pin is configured as ENET_TX_EN */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */ + IOCON_PinMuxSet(IOCON, 4U, 13U, port4_pin13_config); + + const uint32_t port4_pin14_config = (/* Pin is configured as ENET_RX_CLK */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */ + IOCON_PinMuxSet(IOCON, 4U, 14U, port4_pin14_config); + + const uint32_t port4_pin15_config = (/* Pin is configured as ENET_MDC */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */ + IOCON_PinMuxSet(IOCON, 4U, 15U, port4_pin15_config); + + const uint32_t port4_pin16_config = (/* Pin is configured as ENET_MDIO */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */ + IOCON_PinMuxSet(IOCON, 4U, 16U, port4_pin16_config); + + const uint32_t port4_pin8_config = (/* Pin is configured as ENET_TXD0 */ + IOCON_PIO_FUNC1 | + /* No addition pin function */ + IOCON_PIO_MODE_INACT | + /* Input function is not inverted */ + IOCON_PIO_INV_DI | + /* Enables digital function */ + IOCON_PIO_DIGITAL_EN | + /* Input filter disabled */ + IOCON_PIO_INPFILT_OFF | + /* Standard mode, output slew rate control is enabled */ + IOCON_PIO_SLEW_STANDARD | + /* Open drain is disabled */ + IOCON_PIO_OPENDRAIN_DI); + /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */ + IOCON_PinMuxSet(IOCON, 4U, 8U, port4_pin8_config); +} + diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp new file mode 100644 index 0000000..9b0b9df --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp @@ -0,0 +1,605 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "cmsis_os.h" + +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" + +#include "fsl_phy.h" + +#include "lpc546xx_emac_config.h" +#include "lpc546xx_emac.h" + +using namespace std::chrono; + +enet_handle_t g_handle; +// RX packet buffer pointers +emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; +// TX packet buffer pointers +emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; +// RX packet payload pointers +uint32_t rx_ptr[ENET_RX_RING_LEN]; + +/******************************************************************************** + * Internal data + ********************************************************************************/ +#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) +#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) + +extern "C" void lpc546xx_init_eth_hardware(void); + +/* \brief Flags for worker thread */ +#define FLAG_TX 1 +#define FLAG_RX 2 + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityNormal) + +#define PHY_TASK_PERIOD 200ms + +LPC546XX_EMAC::LPC546XX_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} + +/******************************************************************************** + * Buffer management + ********************************************************************************/ +/* + * This function will queue a new receive buffer + */ +static void update_read_buffer(enet_rx_bd_struct_t *rxDesc, uint8_t *buf) +{ + enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; + uint32_t control = ENET_RXDESCRIP_RD_OWN_MASK | ENET_RXDESCRIP_RD_BUFF1VALID_MASK | ENET_RXDESCRIP_RD_IOC_MASK; + uint32_t index = rxBdRing->rxGenIdx; + /* Increase the index. */ + index++; + if (index >= ENET_RX_RING_LEN) { + index = 0; + } + + rxBdRing->rxGenIdx = index; + if (buf != NULL) { + rxDesc->buff1Addr = (uint32_t)buf; + } + + rxDesc->buff2Addr = 0; + rxDesc->reserved = 0; + rxDesc->control = control; +} + +/** \brief Free TX buffers that are complete + */ +void LPC546XX_EMAC::tx_reclaim() +{ + /* Get exclusive access */ + TXLockMutex.lock(); + + static uint8_t consume_index = 0; + enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)&g_handle.txBdRing[0]; + + while (consume_index != txBdRing->txConsumIdx) { + /* Free the transmit buffer */ + memory_manager->free(tx_buff[consume_index]); + tx_buff[consume_index] = NULL; + + xTXDCountSem.release(); + + consume_index++; + if (consume_index >= ENET_TX_RING_LEN) { + consume_index = 0; + } + } + /* Restore access */ + TXLockMutex.unlock(); +} + +/** \brief Ethernet receive interrupt handler + * + * This function handles the receive interrupt of LPC546XX. + */ +void LPC546XX_EMAC::rx_isr() +{ + osThreadFlagsSet(thread, FLAG_RX); +} + +void LPC546XX_EMAC::tx_isr() +{ + osThreadFlagsSet(thread, FLAG_TX); +} + +void LPC546XX_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param) +{ + LPC546XX_EMAC *enet = static_cast(param); + + switch (event) { + case kENET_RxIntEvent: + enet->rx_isr(); + break; + case kENET_TxIntEvent: + enet->tx_isr(); + break; + default: + break; + } +} + +/** \brief Low level init of the MAC and PHY. + */ +bool LPC546XX_EMAC::low_level_init_successful() +{ + status_t status; + uint8_t i; + uint32_t refClock; + phy_speed_t phy_speed; + phy_duplex_t phy_duplex; + uint32_t phyAddr = 0; + bool link = false; + enet_config_t config; + uint32_t timeout = 0xFFFU; + + lpc546xx_init_eth_hardware(); + + refClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); + + status = PHY_Init(ENET, phyAddr, refClock); + if (status != kStatus_Success) { + return false; + } + + ENET_GetDefaultConfig(&config); + config.multiqueueCfg = NULL; + + while ((!link) && timeout) { + PHY_GetLinkStatus(ENET, phyAddr, &link); + if (link) { + /* Get link information from PHY */ + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); + + /* Change the MII speed and duplex for actual link status. */ + config.miiSpeed = (enet_mii_speed_t)phy_speed; + config.miiDuplex = (enet_mii_duplex_t)phy_duplex; + } + timeout--; + } + + if (!link) { + return false; + } + + AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rx_desc_start_addr[ENET_RX_RING_LEN], ENET_BUFF_ALIGNMENT); + AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t tx_desc_start_addr[ENET_TX_RING_LEN], ENET_BUFF_ALIGNMENT); + + /* prepare the buffer configuration. */ + enet_buffer_config_t buffCfg = { + ENET_RX_RING_LEN, + ENET_TX_RING_LEN, + &tx_desc_start_addr[0], + &tx_desc_start_addr[0], + &rx_desc_start_addr[0], + &rx_desc_start_addr[ENET_RX_RING_LEN], + rx_ptr, + ENET_BuffSizeAlign(ENET_ETH_MAX_FLEN), + }; + + /* Create buffers for each receive BD */ + for (i = 0; i < ENET_RX_RING_LEN; i++) { + rx_buff[i] = memory_manager->alloc_heap(buffCfg.rxBuffSizeAlign, ENET_BUFF_ALIGNMENT); + if (NULL == rx_buff[i]) { + return false; + } + + rx_ptr[i] = (uint32_t)memory_manager->get_ptr(rx_buff[i]); + } + + ENET_Init(ENET, &config, hwaddr, refClock); + + /* Enable the tx & rx interrupt. */ + ENET_EnableInterrupts(ENET, kENET_DmaTx | kENET_DmaRx); + + /* Create the handler. */ + ENET_CreateHandler(ENET, &g_handle, &config, &buffCfg, &LPC546XX_EMAC::ethernet_callback, this); + + /* Initialize Descriptor. */ + ENET_DescriptorInit(ENET, &config, &buffCfg); + + return true; +} + +/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. + * + * \return a emac_mem_buf_t filled with the received packet (including MAC header) + * NULL on memory error + */ +emac_mem_buf_t *LPC546XX_EMAC::low_level_input() +{ + enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; + enet_rx_bd_struct_t *bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; + emac_mem_buf_t *p = NULL; + emac_mem_buf_t *temp_rxbuf = NULL; + uint32_t length = 0; + + /* Determine if a frame has been received */ + if ((bdPtr->control & ENET_RXDESCRIP_WR_OWN_MASK) != 0) { + return p; + } + +#ifdef LOCK_RX_THREAD + /* Get exclusive access */ + TXLockMutex.lock(); +#endif + + /* Determine if the received frame has an error */ + if ((bdPtr->control & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0) { + /* Re-use the same buffer in case of error */ + update_read_buffer(bdPtr, NULL); + } else { + if (bdPtr->control & ENET_RXDESCRIP_WR_LD_MASK) { + length = (bdPtr->control & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - 4; + } else { + length = rxBdRing->rxBuffSizeAlign; + } + + /* Zero-copy */ + p = rx_buff[rxBdRing->rxGenIdx]; + memory_manager->set_len(p, length); + + /* Attempt to queue new buffer */ + temp_rxbuf = memory_manager->alloc_heap(rxBdRing->rxBuffSizeAlign, ENET_BUFF_ALIGNMENT); + if (NULL == temp_rxbuf) { + /* Re-queue the same buffer */ + update_read_buffer(bdPtr, NULL); + +#ifdef LOCK_RX_THREAD + TXLockMutex.unlock(); +#endif + + return NULL; + } + + rx_buff[rxBdRing->rxGenIdx] = temp_rxbuf; + rx_ptr[rxBdRing->rxGenIdx] = (uint32_t)memory_manager->get_ptr(rx_buff[rxBdRing->rxGenIdx]); + + update_read_buffer(bdPtr, (uint8_t *)rx_ptr[rxBdRing->rxGenIdx]); + } + +#ifdef LOCK_RX_THREAD + osMutexRelease(TXLockMutex); +#endif + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + */ +void LPC546XX_EMAC::input() +{ + emac_mem_buf_t *p; + + /* move received packet into a new pbuf */ + p = low_level_input(); + if (p == NULL) { + return; + } + + emac_link_input_cb(p); +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void LPC546XX_EMAC::thread_function(void *pvParameters) +{ + struct LPC546XX_EMAC *lpc_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); + + MBED_ASSERT(!(flags & osFlagsError)); + + if (flags & FLAG_RX) { + lpc_enet->packet_rx(); + } + + if (flags & FLAG_TX) { + lpc_enet->packet_tx(); + } + } +} + +/** \brief Packet reception task + * + * This task is called when a packet is received. It will + * pass the packet to the LWIP core. + */ +void LPC546XX_EMAC::packet_rx() +{ + enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; + enet_rx_bd_struct_t *bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; + bool suspend = false; + + /* Suspend and command for rx. */ + if (ENET->DMA_CH[0].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK) { + suspend = true; + } + + while ((bdPtr->control & ENET_RXDESCRIP_WR_OWN_MASK) == 0) { + input(); + /* rxGenIdx gets updated, gets the next receive buffer descriptor */ + bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; + } + + /* Set command for rx when it is suspend. */ + if (suspend) { + ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR = ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR; + } +} + +/** \brief Transmit cleanup task + * + * This task is called when a transmit interrupt occurs and + * reclaims the buffer and descriptor used for the packet once + * the packet has been transferred. + */ +void LPC546XX_EMAC::packet_tx() +{ + tx_reclaim(); +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + */ +bool LPC546XX_EMAC::link_out(emac_mem_buf_t *buf) +{ + enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)&g_handle.txBdRing[0]; + uint32_t index = txBdRing->txGenIdx; + + // If buffer is chained or not aligned then make a contiguous aligned copy of it + if (memory_manager->get_next(buf) || + reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { + emac_mem_buf_t *copy_buf; + copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); + if (NULL == copy_buf) { + memory_manager->free(buf); + return false; + } + + // Copy to new buffer and free original + memory_manager->copy(copy_buf, buf); + memory_manager->free(buf); + buf = copy_buf; + } + + /* Check if a descriptor is available for the transfer. */ + if (!xTXDCountSem.try_acquire()) { + memory_manager->free(buf); + return false; + } + + /* Get exclusive access */ + TXLockMutex.lock(); + + /* Save the buffer so that it can be freed when transmit is done */ + tx_buff[index] = buf; + + if (ENET_SendFrame(ENET, &g_handle, static_cast(memory_manager->get_ptr(buf)), memory_manager->get_len(buf)) != kStatus_Success) { + memory_manager->free(buf); + tx_buff[index] = NULL; + return false; + } + + /* Restore access */ + TXLockMutex.unlock(); + + return true; +} + +/******************************************************************************* + * PHY task: monitor link +*******************************************************************************/ + +#define STATE_UNKNOWN (-1) + +int phy_link_status(void) +{ + bool connection_status; + uint32_t phyAddr = 0; + + PHY_GetLinkStatus(ENET, phyAddr, &connection_status); + return (int)connection_status; +} + +void LPC546XX_EMAC::phy_task() +{ + static PHY_STATE prev_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN}; + uint32_t phyAddr = 0; + // Get current status + PHY_STATE crt_state; + bool connection_status; + + PHY_GetLinkStatus(ENET, phyAddr, &connection_status); + crt_state.connected = connection_status; + // Get the actual PHY link speed + PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); + + // Compare with previous state + if (crt_state.connected != prev_state.connected && emac_link_state_cb) { + emac_link_state_cb(crt_state.connected); + } + + if (crt_state.speed != prev_state.speed) { + uint32_t fes = ENET->MAC_CONFIG; + fes &= ~ENET_MAC_CONFIG_FES_MASK; + if (prev_state.speed != (phy_speed_t)STATE_UNKNOWN) { + fes |= ENET_MAC_CONFIG_FES(!crt_state.speed); + } else { + fes |= ENET_MAC_CONFIG_FES(crt_state.speed); + } + + ENET->MAC_CONFIG = fes; + } + + prev_state = crt_state; +} + +bool LPC546XX_EMAC::power_up() +{ + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + /* Worker thread */ + thread = create_new_thread("LPC546XX_EMAC_thread", &LPC546XX_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); + + /* Trigger thread to deal with any RX packets that arrived before thread was started */ + rx_isr(); + + /* PHY monitoring task */ + prev_state.connected = STATE_UNKNOWN; + prev_state.speed = (phy_speed_t)STATE_UNKNOWN; + prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; + + phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &LPC546XX_EMAC::phy_task)); + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + /* Active TX/RX. */ + ENET_StartRxTx(ENET, 1, 1); + + return true; +} + +uint32_t LPC546XX_EMAC::get_mtu_size() const +{ + return LPC546XX_ETH_MTU_SIZE; +} + +uint32_t LPC546XX_EMAC::get_align_preference() const +{ + return ENET_BUFF_ALIGNMENT; +} + +void LPC546XX_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, LPC546XX_ETH_IF_NAME, (size < sizeof(LPC546XX_ETH_IF_NAME)) ? size : sizeof(LPC546XX_ETH_IF_NAME)); +} + +uint8_t LPC546XX_EMAC::get_hwaddr_size() const +{ + return LPC546XX_HWADDR_SIZE; +} + +bool LPC546XX_EMAC::get_hwaddr(uint8_t *addr) const +{ + return false; +} + +void LPC546XX_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, sizeof hwaddr); + ENET_SetMacAddr(ENET, const_cast(addr)); +} + +void LPC546XX_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void LPC546XX_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void LPC546XX_EMAC::add_multicast_group(const uint8_t *addr) +{ + set_all_multicast(true); +} + +void LPC546XX_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void LPC546XX_EMAC::set_all_multicast(bool all) +{ + uint32_t reg = ENET->MAC_FRAME_FILTER; + + if (all) { + reg |= ENET_MAC_FRAME_FILTER_PM_MASK; + } else { + reg &= ~ENET_MAC_FRAME_FILTER_PM_MASK; + } + + ENET->MAC_FRAME_FILTER = reg; +} + +void LPC546XX_EMAC::power_down() +{ + /* No-op at this stage */ +} + +void LPC546XX_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +LPC546XX_EMAC &LPC546XX_EMAC::get_instance() +{ + static LPC546XX_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return LPC546XX_EMAC::get_instance(); +} + +/** + * @} + */ + +/* --------------------------------- End Of File ------------------------------ */ + diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h new file mode 100644 index 0000000..570a7a5 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LPC546XX_EMAC_H_ +#define LPC546XX_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class LPC546XX_EMAC : public EMAC { +public: + LPC546XX_EMAC(); + + static LPC546XX_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + bool low_level_init_successful(); + void rx_isr(); + void tx_isr(); + void packet_rx(); + void packet_tx(); + void tx_reclaim(); + void input(); + emac_mem_buf_t *low_level_input(); + static void thread_function(void* pvParameters); + void phy_task(); + static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param); + + mbed_rtos_storage_thread_t thread_cb; + osThreadId_t thread; /**< Processing thread */ + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + int phy_task_handle; /**< Handle for phy task event */ + struct PHY_STATE { + int connected; + phy_speed_t speed; + phy_duplex_t duplex; + }; + PHY_STATE prev_state; + uint8_t hwaddr[LPC546XX_HWADDR_SIZE]; +}; + +#endif /* LPC546XX_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h new file mode 100644 index 0000000..72df09f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h @@ -0,0 +1,33 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef LPC546XX_EMAC_CONFIG_H__ +#define LPC546XX_EMAC_CONFIG_H__ + +#include "fsl_enet.h" + +#define ENET_RX_RING_LEN (16) +#define ENET_TX_RING_LEN (8) + +#define ENET_ETH_MAX_FLEN (ENET_FRAME_MAX_FRAMELEN) +#define LPC546XX_HWADDR_SIZE (6) + +#define LPC546XX_ETH_MTU_SIZE 1500 +#define LPC546XX_ETH_IF_NAME "en" + +#define THREAD_STACKSIZE 512 + +#endif // #define LPC546XX_EMAC_CONFIG_H__ + diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/RdaWiFiInterface.cpp b/connectivity/drivers/emac/TARGET_RDA_EMAC/RdaWiFiInterface.cpp new file mode 100644 index 0000000..c68b732 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/RdaWiFiInterface.cpp @@ -0,0 +1,364 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WiFiInterface.h" +#include "RdaWiFiInterface.h" +#include "rda5991h_wland.h" +#include "nsapi_types.h" +#include "wland_types.h" +#include "rda_sys_wrapper.h" + +typedef enum { + WIFI_CONNECTED, + WIFI_DISCONNECTED, +}WIFI_STATE; + +static WIFI_STATE wifi_state = WIFI_DISCONNECTED; + +void daemon(void *para) +{ + void *main_msgQ = NULL; + rda_msg msg; + int ret; + RDAWiFiInterface *wifi = (RDAWiFiInterface *)para; + main_msgQ = rda_mail_create(10, sizeof(unsigned int)*4); + wifi->set_msg_queue(main_msgQ); + while(1){ + rda_mail_get(main_msgQ, (void*)&msg, osWaitForever); + switch(msg.type) + { + case MAIN_RECONNECT: + printf("wifi disconnect!\r\n"); + ret = wifi->disconnect(); + if(ret != 0){ + printf("disconnect failed!\r\n"); + break; + } + ret = wifi->reconnect(); + while(ret != 0){ + osDelay(5*1000); + ret = wifi->reconnect(); + }; + break; + default: + printf("unknown msg\r\n"); + break; + } + } +} + +nsapi_error_t RDAWiFiInterface::set_channel(uint8_t channel) +{ + int ret= 0; + init(); + + if (channel > 13) + return NSAPI_ERROR_PARAMETER; + + if (channel == 0) { + _channel = 0; + return NSAPI_ERROR_OK; + } + + ret = rda5981_set_channel(channel); + if (ret == 0) { + _channel = channel; + return NSAPI_ERROR_OK; + } else { + return NSAPI_ERROR_TIMEOUT; + } +} + +int8_t RDAWiFiInterface::get_rssi() +{ + return rda5981_get_rssi(); +} + +nsapi_error_t RDAWiFiInterface::init() +{ + if (!_interface) { + if (!_emac.power_up()) { + LWIP_DEBUGF(NETIF_DEBUG,("power up failed!\n")); + } + nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); + if (err != NSAPI_ERROR_OK) { + _interface = NULL; + return err; + } + _interface->attach(_connection_status_cb); + //rda_thread_new("daemon", daemon, this, DEFAULT_THREAD_STACKSIZE*4, osPriorityNormal); + } + return NSAPI_ERROR_OK; +} + +nsapi_error_t RDAWiFiInterface::set_credentials(const char *ssid, const char *pass, + nsapi_security_t security) +{ + if (ssid == 0 || strlen(ssid) == 0) { + return NSAPI_ERROR_PARAMETER; + } + if (security != NSAPI_SECURITY_NONE && (pass == 0 || strlen(pass) == 0)) { + return NSAPI_ERROR_PARAMETER; + } + if (strlen(ssid) > 32 || strlen(pass) > 63) { + return NSAPI_ERROR_PARAMETER; + } + memcpy((void*)_ssid, (void*)ssid, strlen(ssid)); + _ssid[strlen(ssid)] = '\0'; + memcpy((void*)_pass, (void*)pass, strlen(pass)); + _pass[strlen(pass)] = '\0'; + _security = security; + return NSAPI_ERROR_OK; +} + +nsapi_error_t RDAWiFiInterface::connect(const char *ssid, const char *pass, + nsapi_security_t security, uint8_t channel) +{ + rda_msg msg; + bool find = false; + int i = 0; + rda5981_scan_result bss; + int ret = 0; + + if(wifi_state == WIFI_CONNECTED) { + return NSAPI_ERROR_IS_CONNECTED; + } + + if (ssid == NULL || ssid[0] == 0) { + return NSAPI_ERROR_PARAMETER; + } + + set_credentials(ssid, pass, security); + set_channel(channel); + + init(); + + //reset all scan result to avoid any previous stored SSID/PW/CHANNEL + rda5981_del_scan_all_result(); + rda5981_scan(NULL,0,0); + if(rda5981_check_scan_result_name(ssid) != 0) { + for (i = 0; i< 5; i++) { + rda5981_scan(NULL, 0, 0); + if(rda5981_check_scan_result_name(ssid) == 0) { + find = true; + break; + } + } + } else { + find = true; + } + + if (find == false) { + LWIP_DEBUGF(NETIF_DEBUG,("can not find the ap.\r\n")); + return NSAPI_ERROR_NO_SSID; + } + bss.channel = 15; + rda5981_get_scan_result_name(&bss, ssid); + if ((channel !=0) && (bss.channel != channel)) { + LWIP_DEBUGF(NETIF_DEBUG, ("invalid channel\r\n")); + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + memcpy(gssid, ssid, strlen(ssid)); + if (pass[0] != 0) { + memcpy(gpass, pass, strlen(pass)); + } + memset(gbssid, 0, NSAPI_MAC_BYTES); + gssid[strlen(ssid)] = gpass[strlen(pass)] = '\0'; + + msg.type = WLAND_CONNECT; + rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); + ret = rda_sem_wait(wifi_auth_sem, 10000); + if (ret) { + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + wifi_state = WIFI_CONNECTED; + + ret = _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK, + _blocking); + LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret)); + + if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) { + ret = NSAPI_ERROR_OK; + } + else if( ret == NSAPI_ERROR_DHCP_FAILURE) { + disconnect(); + } + + return ret; +} + + +nsapi_error_t RDAWiFiInterface::connect() +{ + return connect(_ssid, _pass, _security, _channel); +} + +nsapi_error_t RDAWiFiInterface::disconnect() +{ + rda_msg msg; + + if(wifi_state == WIFI_DISCONNECTED) { + return NSAPI_ERROR_NO_CONNECTION; + } + wifi_state = WIFI_DISCONNECTED; + void* wifi_disconnect_sem = rda_sem_create(0); + msg.type = WLAND_DISCONNECT; + msg.arg1 = (unsigned int)wifi_disconnect_sem; + rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); + rda_sem_wait(wifi_disconnect_sem, osWaitForever); + rda_sem_delete(wifi_disconnect_sem); + if (_interface) { + return _interface->bringdown(); + } + + return NSAPI_ERROR_NO_CONNECTION; +} + +nsapi_error_t RDAWiFiInterface::reconnect() +{ + rda_msg msg; + bool find = false; + int i = 0; + rda5981_scan_result bss; + int ret = 0; + + if (_ssid == NULL || _ssid[0] == 0) { + return NSAPI_ERROR_PARAMETER; + } + + rda5981_del_scan_all_result(); + if(rda5981_check_scan_result_name(_ssid) != 0) { + for (i = 0; i< 5; i++) { + rda5981_scan(NULL, 0, 0); + if(rda5981_check_scan_result_name(_ssid) == 0) { + find = true; + break; + } + } + } else { + find = true; + } + + if (find == false) { + LWIP_DEBUGF(NETIF_DEBUG,"can not find the ap.\r\n"); + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + bss.channel = 15; + rda5981_get_scan_result_name(&bss, _ssid); + if ((_channel !=0) && (bss.channel != _channel)) { + LWIP_DEBUGF(NETIF_DEBUG, "invalid channel\r\n"); + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + memcpy(gssid, _ssid, strlen(_ssid)); + if (_pass[0] != 0) { + memcpy(gpass, _pass, strlen(_pass)); + } + memset(gbssid, 0, NSAPI_MAC_BYTES); + gssid[strlen(_ssid)] = gpass[strlen(_pass)] = '\0'; + + msg.type = WLAND_CONNECT; + rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); + ret = rda_sem_wait(wifi_auth_sem, 10000); + if (ret) { + return NSAPI_ERROR_CONNECTION_TIMEOUT; + } + + if(_dhcp) { + memset(_ip_address, 0, sizeof(_ip_address)); + memset(_netmask, 0, sizeof(_netmask)); + memset(_gateway, 0, sizeof(_gateway)); + } + + ret = _interface->bringup(_dhcp, + _ip_address[0] ? _ip_address : 0, + _netmask[0] ? _netmask : 0, + _gateway[0] ? _gateway : 0, + DEFAULT_STACK, + _blocking); + LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret)); + + if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) { + ret = NSAPI_ERROR_OK; + wifi_state = WIFI_CONNECTED; + } + else if( ret == NSAPI_ERROR_DHCP_FAILURE) { + disconnect(); + } + return ret; +} + + +nsapi_size_or_error_t RDAWiFiInterface::scan(WiFiAccessPoint *res, nsapi_size_t count) +{ + int bss_num = 0, i; + rda5981_scan_result *bss; + nsapi_wifi_ap_t ap; + + init(); + + rda5981_scan(NULL, 0, 0); + bss_num = rda5981_get_scan_num(); + if (count != 0) { + bss_num = (bss_num < count) ? bss_num : count; + } + if (res) { + bss = (rda5981_scan_result *)malloc(bss_num * sizeof(rda5981_scan_result)); + rda5981_get_scan_result(bss, bss_num); + for (i=0; i +#ifdef __cplusplus +extern "C" { +#endif + +extern const unsigned int RDA_FW_INFO_ADDR; +extern const unsigned int RDA_UPGRADE_ADDR; + +/* + * function: start to wirte a partition. this func will erase given flash region + * @addr: partition start address, must be 4k alignment + * @img_len: length of image getted from OTA server, must be 4k alignment + * return: 0:success, else:fail + */ +int rda5981_write_partition_start(unsigned int addr, unsigned int img_len); + +/* + * function: write image to flash, without erase. + * the write region must be inside of the area given by func rda5981_write_partition_start + * the write region must be in order, otherwise the end function will return crc error. + * the maximum length could be write once time is 0x1000 + * @offset: offset from image inital position, must be 1k alignment + * @buf: data to be written + * @len: buffer len, max #0x1000, must be 1k alignment + * return: 0:success, else:fail + */ +int rda5981_write_partition(unsigned int offset, const unsigned char *buf, unsigned int len); + +/* + * function: end of writing partition + * return: 0:crc32 check success, else:fail + */ +int rda5981_write_partition_end(void); + +#ifdef __cplusplus +} +#endif + +#endif /*_RDA5981_OTA_H_*/ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h new file mode 100644 index 0000000..0f0f465 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h @@ -0,0 +1,99 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RDA5981_SNIFFER_H_ +#define _RDA5981_SNIFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "wland_types.h" + +/* Enable filtering ACK frames (no support)*/ +//#define RDA_RX_FILTER_DROP_ACK BIT0 + +/* Enable filtering CTS frames (no support)*/ +//#define RDA_RX_FILTER_DROP_CTS BIT1 + +/* Enable filtering RTS frames (no support)*/ +//#define RDA_RX_FILTER_DROP_RTS BIT2 + +/* Enable filtering beacon frames */ +#define RDA_RX_FILTER_DROP_BEACON BIT3 + +/* Enable filtering ATIM frames (no support)*/ +//#define RDA_RX_FILTER_DROP_ATIM BIT4 + +/* Enable filtering CF_END frames (no support)*/ +//#define RDA_RX_FILTER_DROP_CF_END BIT5 + +/* Enable filtering QCF_POLL frames (no support)*/ +//#define RDA_RX_FILTER_DROP_QCF_POLL BIT6 + +/* Filter Management frames which are not directed to current STA */ +#define RDA_RX_FILTER_DROP_ND_MGMT BIT7 + +/* Filter BC/MC MGMT frames belonging to other BSS */ +#define RDA_RX_FILTER_DROP_BC_MC_MGMT_OTHER_BSS BIT8 + +/* Enable filtering of duplicate frames */ +#define RDA_RX_FILTER_DROP_DUPLICATE BIT9 + +/* Enable filtering of frames whose FCS has failed */ +#define RDA_RX_FILTER_DROP_FCS_FAILED BIT10 + +/* Enable filtering of De-authentication frame */ +#define RDA_RX_FILTER_DROP_DEAUTH BIT11 + +/* Filter BA frames which are not received as SIFS response (no support)*/ +//#define RDA_RX_FILTER_DROP_NSIFS_RESP_BA BIT12 + +/* Filter BA frames which are received as SIFS response (no support)*/ +//#define RDA_RX_FILTER_DROP_SIFS_RESP_BA BIT13 + +/* Filter frames which are received in secondary channel (20 MHz PPDU from Secondary channel) */ +#define RDA_RX_FILTER_DROP_SEC_CHANNEL BIT14 + +/* Filter BC/MC DATA frames belonging to other BSS */ +#define RDA_RX_FILTER_DROP_BC_MC_DATA_OTHER_BSS BIT15 + +/* Filter DATA frames not directed to this station */ +#define RDA_RX_FILTER_DROP_ND_DATA BIT16 + +/* Filter Control frames which are not directed to current STA (no support)*/ +//#define RDA_RX_FILTER_DROP_ND_CONTROL BIT17 + +/* Filter Beacon frames (in IBSS mode) which are not used for adoption because the timestamp field is lower than TSF timer */ +#define RDA_RX_FILTER_DROP_IBSS_BEACON BIT18 + +typedef int (*sniffer_handler_t)(unsigned short data_len, void *data); + +int rda5981_enable_sniffer(sniffer_handler_t handler); +int rda5981_disable_sniffer(void); +//don't use this in sniffer callback handler +int rda5981_disable_sniffer_nocallback(void); +///TODO: time is no use anymore +int rda5981_start_sniffer(unsigned char channel, unsigned char to_ds, + unsigned char from_ds, unsigned char mgm_frame, unsigned short time); +int rda5981_stop_sniffer(void); +int wland_sniffer_set_channel(unsigned char channel); +int rda5981_set_filter(unsigned char to_ds, unsigned char from_ds, unsigned int mgm_filter); +int rda5981_sniffer_enable_fcs(void);//for hiflying +#ifdef __cplusplus +} +#endif + +#endif /*_RDA5981_SNIFFER_H_*/ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h new file mode 100644 index 0000000..38df3e8 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h @@ -0,0 +1,659 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _RDA5991H_WLAND_H_ +#define _RDA5991H_WLAND_H_ + +#include "sys_arch.h" +#include "wland_types.h" + +/* Mbed interface mac address + * if MBED_MAC_ADD_x are zero, interface uid sets mac address, + * otherwise MAC_ADD_x are used. + */ + +extern unsigned char user_mac[6];//not save in flash, need fill before wifi init every time +extern unsigned char gssid[32+1]; +extern unsigned char gpass[64+1]; +extern unsigned char gchannel; +extern unsigned char gbssid[6]; + +extern unsigned char gssid_ap[32+1]; +extern unsigned char gpass_ap[64+1]; +extern unsigned char gchannel_ap; +extern void *wland_msgQ; +extern void *wifi_auth_sem; + +extern u8 sta_state; + +typedef enum { + WLAND_CONNECT, + WLAND_RECONNECT, + WLAND_DISCONNECT, + WLAND_DISCONNECT_ERROR, + WLAND_STARTAP, + WLAND_STOPAP, + WLAND_ADD_AP_GTK, + WLAND_AP_EAPOL_3_OF_4, + WLAND_ADD_AP_PTK, + WLAND_STAJOINED, + WLAND_STAEXITED, + WLAND_STADEAUTH, + WLAND_STADELETETIMER, + WLAND_MAC_CONNECTED, + WLAND_MAC_AP_CONNECTED, + WLAND_ADD_GTK, + WLAND_ADD_PTK, + WLAND_CON_FINISH, + WLAND_AUTO_RATE, + WLAND_ARP_OFFLOAD, + WLAND_SM_START, + WLAND_SM_STOP, + WLAND_WPS_CONNECT, + WLAND_WPS_START, + WLAND_WPS_DISCONNECT, +}WLAND_MSG; + +typedef enum { + MAIN_CONNECT, + MAIN_RECONNECT, + MAIN_DISCONNECT, + MAIN_STOP_AP, +}MAIN_MSG; + +typedef struct { + unsigned int type; + unsigned int arg1; + unsigned int arg2; + unsigned int arg3; +}rda_msg; + + +enum { + D_NONE_LEVEL = 0, + D_ERROR_LEVEL = 1, + D_INFO_LEVEL = 2, + D_DEBUG_LEVEL = 3, +}; + +#define WLAND_DBG_DUMP 0 +#define WPA_DBG_DUMP 0 +#define HUT_DBG_DUMP 0 +#define WLAND_DBG_LEVEL D_NONE_LEVEL +#define WPA_DBG_LEBEL D_NONE_LEVEL +#define WLANDLIB_DBG_LEVEL D_NONE_LEVEL + +#define ETH_ALEN 6 + +//encrypt type +#define ENCRYPT_NONE (0) +#define ENCRYPT_WPA_TKIP BIT0 +#define ENCRYPT_WPA_CCMP BIT1 +#define ENCRYPT_WPA2_TKIP BIT2 +#define ENCRYPT_WPA2_CCMP BIT3 +#define ENCRYPT_WEP BIT4 + +/* r91h driver data structure */ +typedef struct { + struct netif *netif_sta; + struct netif *netif_ap; + sys_thread_t wland_thread; + sys_thread_t maclib_thread; + sys_mbox_t maclib_mbox; + sys_mbox_t wland_mbox; +} rda_enetdata_t; + +__STATIC_INLINE int mac_is_valid(char* mac) +{ + return (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]); +} + + +#ifdef __cplusplus +extern "C" { +#endif + +extern void wland_txip_data(void *data, unsigned int len, int mode); +extern void *wland_get_databuf(void); +extern void wland_sta_init(void); +extern void wland_reg_func(void); +extern void r91h_phy_task(void *data); +extern void wland_task(void *arg); +extern void rda_get_macaddr(u8_t *macaddr, int mode); +extern void rda5981_send_rawdata(char* data, unsigned int len); +extern int rda5981_send_nulldata(int power_save); +extern void rda5981_set_country_code(unsigned char country_code);// 0~china(1-14) 1~NA(1-11) 2~EU(1-13) +extern int rda5981_set_retrans_policy(unsigned char count); +extern int rda5981_set_channel(unsigned char channel); +/* default is 0, receive multicast packet, disable please set 1*/ +extern int rda5981_filter_multicast(unsigned char enable); +/* default is 0, 0 ~ no hidden, 1 ~ hidden zero len, 2 ~ hidden zero contents */ +extern void rda5981_set_AP_hidden_type(unsigned char mode); +extern void rda5981_set_AP_link_num(unsigned char num); +extern char* rda5981_get_ver(void); +extern int rda5981_enter_CE_MODE(unsigned char enable); +/* + * mode 0 - not 11n 1 - 11n + * + * -----------------11n(mode 1)(Mbps)----------------- + * rate HT20 HT40 + * GI(800ns) GI(400ns) GI(800ns) GI(400ns) + * 0 6.5 7.2 13.5 15 + * 1 13 14.2 27 30 + * 2 19.5 21.7 40.5 45 + * 3 26 28.9 54 60 + * 4 39 43.3 81 90 + * 5 52 57.8 108 120 + * 6 58.5 65 121.5 135 + * 7 65 72 135 150 + * + * --------------not 11n(mode 0)(Mbps)----------------- + * rate data rate rate data rate + * 0 autorate 9 9 + * 1 1 12 12 + * 2 2 18 18 + * 5 5.5 24 24 + * 11 11 36 36 + * 6 6 48 48 + * + */ +extern int rda5981_set_data_rate(unsigned char mode, unsigned char rate); +extern void rda5981_set_mode(unsigned char bgn_enable); +extern void rda5981_set_auth_timeout(unsigned char timeout_enable); +typedef struct { + char BSSID[ETH_ALEN]; + char SSID[32+1]; + signed char RSSI; + unsigned char SSID_len; + unsigned char channel; + unsigned char secure_type;//refer #define ENCRYPT_XXX + unsigned char wmm; + unsigned char *ie;//user program couldn't free(ie); + unsigned short capability; + unsigned int ie_length; +} rda5981_scan_result; + +typedef struct { + unsigned char mac[ETH_ALEN]; + unsigned int ip; +} rda5981_apsta_info; + +//scan one or all channel(if channel is 0) once +int rda5981_scan(const char *SSID, const unsigned char SSID_len, const unsigned char channel); +//0 passive mode, 1 active mode, scan time(unit is second) +int rda5981_scan_v2(const char *SSID, const unsigned char SSID_len, const unsigned char channel, const unsigned char mode, \ + const unsigned char scan_time); +int rda5981_get_scan_num(); +int rda5981_get_scan_result(rda5981_scan_result *buf, const unsigned char len); +int rda5981_get_scan_result_index(rda5981_scan_result *buf, const unsigned char index); +int rda5981_get_scan_result_name(rda5981_scan_result *buf, const char *name); +int rda5981_get_scan_result_bssid(rda5981_scan_result *buf, const unsigned char *bssid); +int rda5981_check_scan_result_name(const char *name); +int rda5981_check_scan_result(const char *ssid, const char *bssid, const unsigned channel); +int rda5981_check_scan_result_name_bssid(const unsigned char *name, const unsigned char *bssid); +int rda5981_del_scan_all_result(void); +void rda5981_set_expired_time(unsigned int expired_time); +int rda5981_get_joined_AP(rda5981_scan_result *bss); +s8 rda5981_get_rssi(); +void rda5981_set_main_queue(void* queue); + +void rda5981_set_sta_listen_interval(unsigned char interval); +void rda5981_set_sta_link_loss_time(unsigned char time); +unsigned int rda5981_get_ap_join_info(rda5981_apsta_info *buf, const unsigned char len); +void rda5981_set_AP_white_list(unsigned char flag, unsigned char *mac); +int wland_set_joined_sta_ip(char *mac, unsigned int ip); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_mac_addr(unsigned char *mac_addr); +int rda5981_flash_write_mac_addr(unsigned char *mac_addr); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_uart(void); +int rda5981_flash_read_uart(unsigned int *uart); +int rda5981_flash_write_uart(unsigned int *uart); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ip_addr(unsigned char *ip_addr, unsigned char *server_addr); +int rda5981_flash_write_ip_addr(unsigned char *ip_add, unsigned char *server_addr); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_dhcp_data(void); +int rda5981_flash_read_dhcp_data(unsigned int *enable, unsigned int *ip, unsigned int *msk, unsigned int *gw); +int rda5981_flash_write_dhcp_data(unsigned int enable, unsigned int ip, unsigned int msk, unsigned int gw); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel); +int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel); +int rda5981_flash_erase_ap_data(void); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, + unsigned int *dhcps, unsigned int *dhcpe); +int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, + unsigned int dhcps, unsigned int dhcpe); +int rda5981_flash_erase_ap_net_data(void); + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_sta_data(char *ssid, char *passwd); +int rda5981_flash_write_sta_data(const char *ssid, const char *passwd); +int rda5981_flash_erase_sta_data(void); + + +/* + * read 3rd parter data length from flash + * return user data length + */ +int rda5981_flash_read_3rdparter_data_length(void); + +/* + * read 3rd parter data from flash + * @buf, buf to store user data + * @buf_len, length of buf + * return user data length + */ +int rda5981_flash_read_3rdparter_data(unsigned char *buf, unsigned int buf_len); + +/* + * write 3rd parter data from flash + * @buf, data to write + * @buf_len, length of buf. + * return 0:ok, else:fail + */ +int rda5981_flash_write_3rdparter_data(const unsigned char *buf, unsigned int buf_len); + +/* + * erase 3rd parter data from flash + * return 0:ok, else:fail + */ +int rda5981_flash_erase_3rdparter_data(void); + +/* + * set flash size + * @size, 1MB:0x100000, 2MB:0x200000, 4MB:0x400000. default size: 1MB + * return 0:ok, else:fail + */ +int rda5981_set_flash_size(const unsigned int size); + +/* + * set userdata location on flash + * @sys_data_addr, data to save system parameter, user can not operate this area directly. + * size:4KB. default location:0x180fb000 + * @user_data_addr, data to save user data. user can save own data in this area + * by @rda5981_flash_read_3rdparter_data + * and @rda5981_flash_write_3rdparter_data + * default location:0x180fc000 + * @user_data_len, user data length, default:4KB + * return 0:ok, else:fail + */ +int rda5981_set_user_data_addr(const unsigned int sys_data_addr, + const unsigned int user_data_addr, const unsigned int user_data_len); + +/* + * function: erase flash + * @addr: mast be 4k alignment + * @len: must be 4k alignment. (package 64KB erase and 4KB erase for different condition automatically) + * return: 0:success, else:fail + */ +int rda5981_erase_flash(unsigned int addr, unsigned int len); + +/* + * function: write flash + * @addr: mast be 256 alignment + * @buf: data to be written, best be 4 alignment + * @len: buffer len, mast be 4 alignment + * return: 0:success, else:fail + */ +int rda5981_write_flash(unsigned int addr, char *buf, unsigned int len); + +/* + * function: read flash to @buf + * @addr: best be 4 alignment + * @buf: best be 4 alignment + * @len: buffer len + * return: 0:success, else:fail + */ +int rda5981_read_flash(unsigned int addr, char *buf, unsigned int len); + +/* + * function: read user data + * @data: data to read + * @len: length of data in byte + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_read_user_data(unsigned char *data, unsigned short len, unsigned int flag); + +/* + * function: write user data + * @data: data to write + * @len: length of data in byte + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_write_user_data(unsigned char *data, unsigned short len, unsigned int flag); + +/* + * function: erase user data + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_erase_user_data(unsigned int flag); + +/* + * function: update tx power from efuse data, for reg 11F and 120 + * return: 0:success, else:fail + */ +int update_tx_power_from_efuse(void); + +/* + * function: update xtal calibration from efuse data, for reg DA + * return: 0:success, else:fail + */ +int update_xtal_cal_from_efuse(void); + +/* + * function: update mac addr from flash data + * return: 0:success, else:fail + */ +int update_mac_addr_from_efuse(void); + +/* + * function: update tx power from flash data, Deprecated version + * return: 0:success, else:fail + */ +int update_tx_power_from_flash(void); + +/* + * function: update tx power from flash data, for reg 8A + * return: 0:success, else:fail + */ +int update_tx_power_rf_from_flash(void); + +/* + * function: update tx power from flash data, for reg 11F and 120 + * return: 0:success, else:fail + */ +int update_tx_power_phy_from_flash(void); + +/* + * function: update xtal calibration from flash data + * return: 0:success, else:fail + */ +int update_xtal_cal_from_flash(void); + +/* + * function: update mac addr from flash data + * return: 0:success, else:fail + */ +int update_mac_addr_from_flash(void); + +/* + * function: write rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + * eg: 0x00DA:xtal calibration + */ +int wland_rf_write(unsigned short reg, unsigned short value); + +/* + * function: write rf reg + * @reg: rf reg data + * @value: rf reg value + * @len : value length + * return: 0:success, else:fail + * eg: 0x008A:tx power rf + */ +int wland_rf_write_all_channels(unsigned short reg, unsigned short *value, unsigned short len); + +/* + * function: read rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + */ +int wland_rf_read(unsigned short reg, unsigned short *value); + +/* + * function: read rf reg + * @reg: rf reg data + * @value: rf reg value + * return: 0:success, else:fail + * eg: 0x008A:tx power rf + */ +int wland_rf_read_all_channels(unsigned short reg, unsigned short *value); + +/* + * function: write phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_write(unsigned int reg, unsigned int value); + +/* + * function: write phy reg + * @reg: phy reg data + * @value: phy reg value + * @len : value length + * return: 0:success, else:fail + */ +int wland_phy_write_all_channels(unsigned int reg, unsigned int *value, unsigned short len); + +/* + * function: read phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_read(unsigned int reg, unsigned int *value); + +/* + * function: read phy reg + * @reg: phy reg data + * @value: phy reg value + * return: 0:success, else:fail + */ +int wland_phy_read_all_channels(unsigned int reg, unsigned int *value); + +/* efuse API start */ +/* Efuse CAN ONLY WRITE ONCE! DO NOT CALL THESE API IF YOU DO KNOW WHAT THEY MEANS!!! */ + +/* + * function: read all efuse + * @value: buffer to store efuse data, 28 bytes + * return: 0:success, else:fail + */ +int wland_read_efuse(unsigned char *value); + +/* + * function: read tx power from efuse + * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54). + * return: 0:success, else:fail + */ +int wland_read_tx_power_from_efuse(unsigned char *tx_power); + +/* + * function: read tx power from efuse + * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54) + * @len: must be 2 + * return: 0:success, else:fail + */ +int wland_write_tx_power_to_efuse(unsigned char *tx_power, unsigned char len); + +/* + * function: read xtal cal from efuse + * @xtal_cal: 1 byte, maximum 0x7F + * return: 0:success, else:fail + */ +int wland_read_xtal_cal_from_efuse(unsigned char *cal_val); + +/* + * function: write xtal cal to efuse + * @xtal_cal: 1 byte, maximum 0x7F + * @len : must be 1 + * return: 0:success, else:fail + */ +int wland_write_xtal_cal_to_efuse(unsigned char *xtal_cal, unsigned char len); + +/* + * function: write mac to efuse + * @xtal_cal: 6 bytes + * return: 0:success, else:fail + */ +int wland_read_mac_addr_from_efuse(unsigned char *mac_addr); + +/* + * function: write mac to efuse + * @xtal_cal: 6 bytes + * @len : must be 6 + * return: 0:success, else:fail + */ +int wland_write_mac_addr_to_efuse(unsigned char*mac_addr, unsigned char len); +/* efuse API end */ + +/* + * function: start rf test + * @argc: number of argv + * @argv: args for test, 6 elements for tx test, 4 elements for rx test + * @is_tx: 1 for tx test, 0 for rx test + * return: 0:success, else:fail + */ +int wland_start_rf_test(unsigned int argc, unsigned int *argv, unsigned int is_tx); + +/* + * function: stop rx test + * return: 0:success, else:fail + */ +int wland_stop_rx_test(void); + +/* + * function: get rf test result + * @result buffer to store rx result + * return: 0:success, else:fail + */ +int wland_get_rx_result(char *result); + +/* + * function: restart rx test, use last rx test args + * return: 0:success, else:fail + */ +int wland_restart_rx_test(void); + +/* + * function: stop tx test + * return: 0:success, else:fail + */ +int wland_stop_tx_test(void); + +/* + * function: restart tx test, use last tx test args + * return: 0:success, else:fail + */ +int wland_restart_tx_test(void); + +#define RDA5981_FIRMWARE_INFO_ADDR 0x18003000 +/* + * function: reboot to assigned addr (onece). + * reboot to rf test mode, not for OTA + * @firmware_info_addr: firmware info addr, depend on your flash layout + * @reboot_addr: reboot addr, 0x18001000-0x1840000 + * return: 0:success, else:fail + */ +int rda5981_reboot_to_addr(unsigned int firmware_info_addr, unsigned int reboot_addr); + +/* + * function: read reg and corresponding value related to test mode stored in flash + * @reg: reg to read + * @value: buffer to store value + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_read_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); + +/* + * function: write reg and corresponding value related to test mode stored in flash + * @reg: reg to write + * @value: buffer that stores value + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_write_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); + +/* + * function: erase reg and corresponding value related to test mode stored in flash + * @reg: reg to erase + * @flag: user data flag + * return: 0:success, else:fail + */ +int rda5981_erase_user_data_regs(unsigned char *reg, unsigned int flag); + +/* + * function: get flash Manufacturer ID + * @mid: + * return: 0:success, else:fail + */ +int rda5981_flash_get_mid(unsigned char *mid); + +/* + * function: get flash Device ID + * @did: + * return: 0:success, else:fail + */ +int rda5981_flash_get_did(unsigned char *did); + +/* + * function: get flash ID + * @mid: + * return: 0:success, else:fail + */ +int rda5981_flash_get_jdid(unsigned short *jdid); + +/* + * function: read mac reg + * @reg: mac reg data + * @value: mac reg value + * return: 0:success, else:fail + */ +int wland_mac_reg_read(unsigned short reg, unsigned int *value); + +/* + * function: write mac reg + * @reg: mac reg data + * @value: mac reg value + * return: 0:success, else:fail + */ +int wland_mac_reg_write(unsigned short reg, unsigned int value); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h new file mode 100644 index 0000000..25b80b5 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h @@ -0,0 +1,216 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if 1 +#ifndef _RDA_SYS_WRAPPER_H_ +#define _RDA_SYS_WRAPPER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Alarm */ +/** + * @brief : get current time in units of micro second + * @param[in] : + * @param[out]: + * @return : return time value with uint32 type + */ +extern unsigned long rda_get_cur_time_ms(void); + +/** + * @brief : create an alarm with given function, return timer handle + * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) + * @param[out]: + * @return : return timer handle, a pointer to the timer structure, non-zero is valid + */ +extern void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode); +extern void * rda_alarm_create(void *func, unsigned int data); + +/** + * @brief : delete an alarm with given handle, then reset the handle + * @param[in] : *handle(pointer to the timer structure) + * @param[out]: **handle(address of the handle variable) + * @return : + */ +extern int rda_alarm_delete(void **handle); + +/** + * @brief : start an alarm, raise a function call after given timeout delay + * @param[in] : handle(pointer to the timer structure)/timeout(micro second) + * @param[out]: + * @return : + */ +extern int rda_alarm_start(void *handle, unsigned int timeout_ms); + +/** + * @brief : stop an alarm, will not raise a function call any more + * @param[in] : handle(pointer to the timer structure) + * @param[out]: + * @return : + */ +extern int rda_alarm_stop(void *handle); + + +/* Semaphore */ +/** + * @brief : create a semaphore + * @param[in] : name and initial valve of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern void* rda_sem_create(unsigned int count); + +/** + * @brief : wait a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_wait(void *sem, unsigned int millisec); + +/** + * @brief : release a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_release(void *sem); + +/** + * @brief : delete a semaphore + * @param[in] : name of semaphore + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_sem_delete(void *sem); + + +/* Queue */ +/** + * @brief : create a message queue + * @param[in] : size of message queue + * @param[out]: + * @return : return message queue id or NULL if error + */ +extern void* rda_msgQ_create(unsigned int queuesz); + +/** + * @brief : put a message to queue + * @param[in] : message queue id, message value and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_msg_put(void *msgQId, unsigned int msg, unsigned int millisec); + +/** + * @brief : get a message from queue + * @param[in] : message queue id, message value and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_msg_get(void *msgQId, unsigned int *value, unsigned int millisec); + +/* Mail */ +/** + * @brief : create a mail + * @param[in] : mail count/size + * @param[out]: + * @return : return mail handle + */ +void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize); + +/** + * @brief : get a msg from mail + * @param[in] : handler name of mail/mail/wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +int rda_mail_get(void *rdahandle, void *evt, unsigned int wait); + +/** + * @brief : put a msg to mail + * @param[in] : handler of mail/mail/wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ + +int rda_mail_put(void *rdahandle, void *evt, unsigned int wait); + +/* Mutex */ +/** + * @brief : create a mutex + * @param[in] : + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern void* rda_mutex_create(void); + +/** + * @brief : wait a mutex + * @param[in] : id of mutex and wait time + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_wait(void *rdamutex, unsigned int millisec); + +/** + * @brief : release a mutex + * @param[in] : id of mutex + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_realease(void *rdamutex); + +/** + * @brief : delete a mutex + * @param[in] : id of mutex + * @param[out]: + * @return : return ERR or NO_ERR + */ +extern int rda_mutex_delete(void *rdamutex); + +/* Thread */ +/** + * @brief : creat a thread + * @param[in] : thread name/thread function/thread fuction argument/stacksize/thread priority + * @param[out]: + * @return : return thread id + */ +void* rda_thread_new(const char *pcName, void (*thread)(void *arg), void *arg, int stacksize, int priority); + +/** + * @brief : delete a thread + * @param[in] : thread id + * @param[out]: + * @return : return ERR or NO_ERR + */ +int rda_thread_delete(void* id); + +/** + * @brief : get current thread id + * @param[in] : + * @param[out]: + * @return : return thread id + */ +void* rda_thread_get_id(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _RDA_SYS_WRAPPER_H_ */ +#endif diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h new file mode 100644 index 0000000..ce418c0 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_DBG_H_ +#define _WLAND_DBG_H_ +#include +#include "rda5991h_wland.h" +#include "wland_types.h" + +extern int wland_dbg_dump; +extern int wland_dbg_level; + +#define RDA_WLAND_DBG + +#ifdef RDA_WLAND_DBG +#define WLAND_DBG(level, fmt, ...) do {\ + int dbg_level = D_##level##_LEVEL;\ + if((dbg_level <= wland_dbg_level)){\ + printf("%s,"fmt, __func__, ##__VA_ARGS__);\ + } \ + } while (0) + +//if frmae_len is zero, get len from frame header +static inline void wland_dump_frame(const char* msg, u8 *data, u32 frame_len) +{ + + u32 len,i; + + if(wland_dbg_dump == 1) { + if(frame_len != 0) { + len = frame_len; + } else { + len = data[0] | ((data[1]&0x0f) << 8); + } + printf("%s : ",msg); + for(i=0; i= 4) { + wait_busy_down_4(); + } else { + wait_busy_down_2(); + } +} + +static void spi_write_reset(void) +{ + if (rda_ccfg_hwver() >= 4) { + spi_write_reset_4(); + } else { + spi_write_reset_2(); + } +} + +static void spi_wip_reset(void) +{ + if (rda_ccfg_hwver() >= 4) { + spi_wip_reset_4(); + } else { + spi_wip_reset_2(); + } +} + +static inline void spi_flash_enable_cache(void) +{ + unsigned int func = spi_flash_cfg_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_cfg_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void spi_flash_disable_cache(void) +{ + unsigned int func = spi_flash_disable_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_disable_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void spi_flash_flush_cache(void) +{ + unsigned int func = spi_flash_flush_cache_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_flush_cache_addr_4; + } + ((void(*)(void))func)(); +} + +static inline void rda5981_spi_flash_erase_4KB_sector(u32 addr) +{ + unsigned int func = spi_flash_erase_4KB_sector_addr; + if (rda_ccfg_hwver() >= 4) { + func = spi_flash_erase_4KB_sector_addr_4; + } + ((void(*)(u32))func)(addr); +} + +static inline void RDA5991H_ERASE_FLASH(void *addr, u32 len) +{ + unsigned int func = FLASH_ERASE_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_ERASE_FUN_ADDR_4; + } + ((void(*)(void *, u32))func)(addr, len); +} + +static inline void RDA5991H_WRITE_FLASH(u32 addr, u8 *data, u32 len) +{ + unsigned int func = FLASH_WRITE_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_WRITE_FUN_ADDR_4; + } + ((void(*)(u32, u8 *, u32))func)(addr, data, len); +} + +static inline void RDA5991H_READ_FLASH(u32 addr, u8 *buf, u32 len) +{ + unsigned int func = FLASH_READ_FUN_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = FLASH_READ_FUN_ADDR_4; + } + ((void(*)(u32, u8 *, u32))func)(addr, buf, len); +} + +static inline void SPI_FLASH_READ_DATA_FOR_MBED(void *addr, void *buf, u32 len) +{ + unsigned int func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR_4; + } + ((void(*)(void *, void *, u32))func)(buf, addr, len); +} + +#endif /*_WLAND_FLASH_H_*/ + diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h new file mode 100644 index 0000000..40ee40e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_FLASH_WP_H_ +#define _WLAND_FLASH_WP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +extern void flash_wrtie_protect_all(); +extern void flash_wrtie_protect_none(); +extern void flash_wrtie_protect(unsigned int offset); +extern void rda5981_flash_init(); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h new file mode 100644 index 0000000..57b9052 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_OTA_H_ +#define _WLAND_OTA_H_ +#include "wland_types.h" +#include "rda_ccfg_api.h" + +extern u32 flash_size; + +#define CRC32_TABLE_ADDR 0xbb5c +#define CRC32_ADDR 0x8dff//u32 crc32(const u8 *p, size_t len) + +#define CRC32_TABLE_ADDR_4 0xbbd8 +#define CRC32_ADDR_4 0x8e33//u32 crc32(const u8 *p, size_t len) + +static inline unsigned int bootrom_crc32(unsigned char *p, unsigned int len) +{ + unsigned int func = CRC32_ADDR; + if (rda_ccfg_hwver() >= 4) { + func = CRC32_ADDR_4; + } + return ((unsigned int(*)(unsigned char *, unsigned int))func)(p, len); +} + +#endif /*_WLAND_OTA_H_*/ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h new file mode 100644 index 0000000..6a9ebeb --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _WLAND_RF_H_ +#define _WLAND_RF_H_ + +#include "wland_types.h" + +#define WLAND_TXP_NUM 2 +#define WLAND_CHANNEL_NUM 14 +#define WLAND_TX_POWER_PHY_GN_REG 0x11F +#define WLAND_TX_POWER_PHY_B_REG 0x120 +#define WLAND_TX_POWER_RF_REG 0x8A +#define WLAND_XTAL_CAL_REG 0xDA + +#define MAKE_WORD16(lsb, msb) (((u16)(msb) << 8) & 0xFF00) | (lsb) +#define MAKE_WORD32(lsw, msw) (((u32)(msw) << 16) & 0xFFFF0000) | (lsw) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h new file mode 100644 index 0000000..3cb0e7e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*****************************************************************************/ +/* */ +/* File Name : wland_types.h */ +/* */ +/* Description : This file contains all the data type definitions for */ +/* MAC implementation. */ +/* */ +/*****************************************************************************/ + +#ifndef WLAND_TYPES_H +#define WLAND_TYPES_H + +/*****************************************************************************/ +/* Constants Definitions */ +/*****************************************************************************/ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; + +typedef unsigned int size_t; + +/** Indicates Bit Value of BITx */ +#ifndef BIT +#define BIT(x) (1ul << (x)) + +/*****************************************************************************/ +/* Constant Definitions */ +/*****************************************************************************/ + +#define BIT0 (1ul << 0) +#define BIT1 (1ul << 1) +#define BIT2 (1ul << 2) +#define BIT3 (1ul << 3) +#define BIT4 (1ul << 4) +#define BIT5 (1ul << 5) +#define BIT6 (1ul << 6) +#define BIT7 (1ul << 7) +#define BIT8 (1ul << 8) +#define BIT9 (1ul << 9) +#define BIT10 (1ul << 10) +#define BIT11 (1ul << 11) +#define BIT12 (1ul << 12) +#define BIT13 (1ul << 13) +#define BIT14 (1ul << 14) +#define BIT15 (1ul << 15) +#define BIT16 (1ul << 16) +#define BIT17 (1ul << 17) +#define BIT18 (1ul << 18) +#define BIT19 (1ul << 19) +#define BIT20 (1ul << 20) +#define BIT21 (1ul << 21) +#define BIT22 (1ul << 22) +#define BIT23 (1ul << 23) +#define BIT24 (1ul << 24) +#define BIT25 (1ul << 25) +#define BIT26 (1ul << 26) +#define BIT27 (1ul << 27) +#define BIT28 (1ul << 28) +#define BIT29 (1ul << 29) +#define BIT30 (1ul << 30) +#define BIT31 (1ul << 31) +#endif + +#endif /* WLAND_TYPES_H */ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt new file mode 100644 index 0000000..24e2529 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt @@ -0,0 +1,49 @@ +Permissive Binary License + +Version 1.0, January 2019 + +Redistribution. Redistribution and use in binary form, without +modification, are permitted provided that the following conditions are +met: + +1) Redistributions must reproduce the above copyright notice and the + following disclaimer in the documentation and/or other materials + provided with the distribution. + +2) Unless to the extent explicitly permitted by law, no reverse + engineering, decompilation, or disassembly of this software is + permitted. + +3) Redistribution as part of a software development kit must include the + accompanying file named �DEPENDENCIES� and any dependencies listed in + that file. + +4) Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +Limited patent license. The copyright holders (and contributors) grant a +worldwide, non-exclusive, no-charge, royalty-free patent license to +make, have made, use, offer to sell, sell, import, and otherwise +transfer this software, where such license applies only to those patent +claims licensable by the copyright holders (and contributors) that are +necessarily infringed by this software. This patent license shall not +apply to any combinations that include this software. No hardware is +licensed hereunder. + +If you institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the software +itself infringes your patent(s), then your rights granted under this +license shall terminate as of the date such litigation is filed. + +DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT +NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md new file mode 100644 index 0000000..5df1aa3 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md @@ -0,0 +1,7 @@ +This directory tree contains binaries build from RDA SDK modified for Mbed OS and released under Permissive Binary License. + +libhal files in the subfolders are generated with toolchains: + +Arm Compiler 5 - version 5.06u6 +GNU Arm Embedded - version 6.3.1 +IAR EWARM - version 8.32.2.178 \ No newline at end of file diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar new file mode 100644 index 0000000..907d766 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar Binary files differ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a new file mode 100644 index 0000000..4d2ed20 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a Binary files differ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a new file mode 100644 index 0000000..a98ce3c --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a Binary files differ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c new file mode 100644 index 0000000..251133e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c @@ -0,0 +1,223 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * @file : maclib_task.c + * @brief : WiFi MACLib task source file + * @version: V1.0 + * @date : 6. May 2017 + * + * @note + * + ******************************************************************************/ +#include +#include +#include + +#include "mbed_interface.h" +#include "cmsis_os.h" +#include "csl_mbed.h" +#include "maclib_task.h" +#include "rda5991h_wland.h" + +#include "lwip/pbuf.h" +#include "lwip/sys.h" + +/** + * Macros + */ +#define MACLIB_TASK_DEBUG (0) + +/** + * Variables + */ +static int maclib_task_run = 0; +static void* maclib_mbox; +static int g_event_num = 0; +static int g_event_proc_done = 1; +static sys_sem_t g_maclib_sem_sleep; +static int g_maclib_sleep_flag = 0; + +extern maclib_func_t *maclib_func_p; + +extern void rda_critical_sec_start(void); +extern void rda_critical_sec_end(void); +extern void wland_set_sta_sleep(unsigned char is_sleep); +/** + * Functions + */ +/* maybe called in isr, should not use "printf", "malloc" */ +void mbed_event_handle_cb(unsigned int event) +{ + static unsigned int sec_cnt = 0; + MACLIB_EVENT_HANDLE_T type = (MACLIB_EVENT_HANDLE_T)event; + if ((maclib_task_run == 0) && (MACLIB_EVENT_CLEANUP != type)) { + mbed_error_printf("evntHndlCb_nulldata\r\n"); + return; + } + switch(type) { + case MACLIB_EVENT_PEND: + rda_critical_sec_start(); + g_event_num++; + if((1 == g_event_num) && (1 == g_event_proc_done)) { + maclib_msg_t msg; +#if MACLIB_TASK_DEBUG + mbed_error_printf("#1-1,%d(%08X)\r\n", g_event_num, __get_xPSR()); +#endif + msg.type = MACLIB_MSG_EVNT_HNDL; + msg.msg = NULL; + rda_mail_put(maclib_mbox, (void*)&msg, 0); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#1-2\r\n"); +#endif + } + rda_critical_sec_end(); + break; + case MACLIB_EVENT_PROCESS: +#if 1 + rda_critical_sec_start(); + g_event_num--; + if(0 > g_event_num) { + mbed_error_printf("event handle err\r\n"); + g_event_num = 0; + } + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#3,%d\r\n",g_event_num); +#endif +#endif + break; + case MACLIB_EVENT_CLEANUP: +#if MACLIB_TASK_DEBUG + mbed_error_printf("event cleanup\r\n"); +#endif + rda_critical_sec_start(); + g_event_num = 0; + rda_critical_sec_end(); + break; + default: + break; + } +} + +void mbed_mltask_sleep_cb(void) +{ + g_maclib_sleep_flag = 1; + sys_arch_sem_wait(&g_maclib_sem_sleep, 0); +} + +void mbed_mltask_wakeup_cb(void) +{ + rda_critical_sec_start(); + if (1 == g_maclib_sleep_flag) { + g_maclib_sleep_flag = 0; + sys_sem_signal(&g_maclib_sem_sleep); + } + rda_critical_sec_end(); +} + +void maclib_check_status(void) +{ + rda_critical_sec_start(); + if (1 == g_maclib_sleep_flag) { + if(*((unsigned int *)0x40020580U) & (0x01UL << 2)) { + mbed_mltask_wakeup_cb(); + } + } + rda_critical_sec_end(); +} + +int maclib_is_sleep_allowed(void) +{ + return g_maclib_sleep_flag; +} + +void maclib_task(void *pvParameters) +{ + int ret; +#if 0 + sleep_entry_t maclib_sleep_entry = { + wland_set_sta_sleep, + maclib_is_sleep_allowed, + maclib_check_status + }; +#endif + sys_sem_new(&g_maclib_sem_sleep, 0); + //sleep_entry_register(&maclib_sleep_entry); + + maclib_mbox = (void *)rda_mail_create(8, sizeof(maclib_msg_t));//ret = sys_mbox_new(&(maclib_mbox), 8); + if(NULL == maclib_mbox) { + mbed_error_printf("msgbox init err!\r\n"); + goto mac_lib_err; + } +#if MACLIB_TASK_DEBUG + LWIP_DEBUGF(NETIF_DEBUG,"#mbox new\r\n"); +#endif + maclib_task_run = 1; + while(1) { + maclib_msg_t msg; + osStatus_t status = rda_mail_get(maclib_mbox, (void *)&msg, osWaitForever); + if(osOK != status) { + mbed_error_printf("ml_task: invalid msg ret=%08X\r\n", status); + continue; + } + switch(msg.type) { + case MACLIB_MSG_EVNT_HNDL: { + rda_critical_sec_start(); + g_event_proc_done = 0; + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#get event %d\r\n", g_event_num); +#endif + maclib_func_p->ml_tasklet(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#5\r\n"); +#endif + rda_critical_sec_start(); +#if 0 + g_event_num--; + if(0 > g_event_num) { + mbed_error_printf("event handle err\r\n"); + } else +#endif + g_event_proc_done = 1; + if(0 < g_event_num) { +#if MACLIB_TASK_DEBUG + mbed_error_printf("#2-1\r\n"); +#endif + rda_mail_put(maclib_mbox, (void*)&msg, 0); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#2-2\r\n"); +#endif + } + rda_critical_sec_end(); +#if MACLIB_TASK_DEBUG + mbed_error_printf("#pDone\r\n"); +#endif + break; + } + default: + break; + } +#if MACLIB_TASK_DEBUG + mbed_error_printf("#4\r\n"); +#endif + } + +mac_lib_err: + LWIP_DEBUGF(NETIF_DEBUG,"MACLib exit!\r\n"); + osDelay(osWaitForever); +} diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c new file mode 100644 index 0000000..d51064e --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c @@ -0,0 +1,530 @@ +/* Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/****************************************************************************** + * @file rda5991h_wland.c + * @brief RDA5991H wlan driver for LWIP + * @version: V1.0 + * @date: 25. July 2016 + * + * @note + * Copyright (C) 2009 ARM Limited. All rights reserved. + * + * @par + * ARM Limited (ARM) is supplying this software for use with Cortex-M + * processor based microcontrollers. This file can be freely distributed + * within development tools that are supporting such ARM based processors. + * + * @par + * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED + * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. + * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR + * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. + * + ******************************************************************************/ + +#include "lwip/opt.h" +#include "lwip/sys.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/stats.h" +#include "lwip/snmp.h" +#include "lwip/tcpip.h" +#include "netif/etharp.h" +#include "sys_arch.h" +#include "rda5991h_wland.h" +#include "cmsis.h" +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +#include "entropy_poll.h" +#else +#include "trng_api.h" +#endif +#include "gpio_api.h" +#include "gpio_irq_api.h" +#include "maclib_task.h" +#include "rda_sys_wrapper.h" +#include +#include +#include +#include + +/* Global variables */ +rda_enetdata_t r91h_wifidata; + +int wland_dbg_dump = WLAND_DBG_DUMP; +int wland_dbg_level = WLAND_DBG_LEVEL; +int wpa_dbg_dump = WPA_DBG_DUMP; +int wpa_dbg_level = WPA_DBG_LEBEL; +int wlandlib_dbg_level = WLANDLIB_DBG_LEVEL; +int hut_dbg_dump = HUT_DBG_DUMP; + +//#define CONFIG_DISABLE_ALL_INT +#define CRI_SEC_START_PRI_LEVEL 0xF8 +#define CRI_SEC_END_PRI_LEVEL 0x00 +static unsigned int g_critical_sec_counter = 0U; +#if defined(CONFIG_DISABLE_ALL_INT) +static unsigned int g_critical_ctxt_saved = 0U; +#endif /* CONFIG_DISABLE_ALL_INT */ +void *packet_rx_queue; + +/* Function statements */ +void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx); +void mbed_mac_address(char *mac); + +/** \brief Driver transmit and receive thread priorities + * + * Thread priorities for receive thread and TX cleanup thread. Alter + * to prioritize receive or transmit bandwidth. In a heavily loaded + * system or with LEIP_DEBUG enabled, the priorities might be better + * the same. */ +#define RX_PRIORITY (osPriorityNormal) +#define TX_PRIORITY (osPriorityNormal) +#define PHY_PRIORITY (osPriorityNormal) + +void rda_netif_down(int netif) +{ + if (netif == 0) { + netif_set_down(r91h_wifidata.netif_sta); + } else { + netif_set_down(r91h_wifidata.netif_ap); + } +} + +void rda_netif_link_down(int netif) +{ + rda_msg msg; + msg.type = 1; + msg.arg1 = 0; + rda_mail_put(packet_rx_queue, (void*)&msg, 0); +} + +void rda_netif_up(int netif) +{ + if (netif == 0) { + netif_set_up(r91h_wifidata.netif_sta); + } else { + netif_set_up(r91h_wifidata.netif_ap); + } +} + +void rda_netif_link_up(int netif) +{ + rda_msg msg; + msg.type = 1; + msg.arg1 = 1; + rda_mail_put(packet_rx_queue, (void*)&msg, 0); + return; +} + +void rda_netif_input(u8_t *data, u32_t len, int idx, int netif) +{ + if (netif == 0) { + r91h_wifiif_input(r91h_wifidata.netif_sta, data, len, idx++); + } else { + r91h_wifiif_input(r91h_wifidata.netif_ap, data, len, idx++); + } +} + +void rda_get_macaddr(u8_t *macaddr, int mode) +{ + mbed_mac_address((char *)macaddr); + if (mode == 1) { + if(macaddr[0] & 0x04) { + macaddr[0] &= 0xFB; + } else { + macaddr[0] |= 0x04; + } + } + return; +} + +void rda_critical_sec_start(void) +{ + if (__get_IPSR() == 0U) { + if (0U == g_critical_sec_counter) { +#if defined(CONFIG_DISABLE_ALL_INT) + g_critical_ctxt_saved = __disable_irq(); +#else /* CONFIG_DISABLE_ALL_INT */ + __set_BASEPRI(CRI_SEC_START_PRI_LEVEL); +#endif /* CONFIG_DISABLE_ALL_INT */ + } + g_critical_sec_counter++; + } +} + +void rda_critical_sec_end(void) +{ + if (__get_IPSR() == 0U) { + g_critical_sec_counter--; + if (0U == g_critical_sec_counter) { +#if defined(CONFIG_DISABLE_ALL_INT) + __set_PRIMASK(g_critical_ctxt_saved); +#else /* CONFIG_DISABLE_ALL_INT */ + __set_BASEPRI(CRI_SEC_END_PRI_LEVEL); +#endif /* CONFIG_DISABLE_ALL_INT */ + } + } +} + +unsigned int rda_critical_sec_counter_get(void) +{ + if (__get_IPSR() == 0U) { + return g_critical_sec_counter; + } else { + return 0xFFFFFFFF; + } +} + +void rda_critical_sec_start_resume(unsigned int cnt) +{ + unsigned int i = 0; + for(i=0; inext) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + /* load rx data from 96 to local mem_pool */ + MEMCPY(q->payload, &data[index], q->len); + index += q->len; + + if (index >= len) { + break; + } + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } else { + /* Drop this packet */ + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + + return NULL; + } + + return p; +} + +/** \brief Attempt to read a packet from the EMAC interface. + * + * \param[in] netif the lwip network interface structure + * \param[in] idx index of packet to be read + */ +void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx) +{ + rda_msg msg; + msg.type = 0; + msg.arg1 = (int)data; + msg.arg2 = len; + rda_mail_put(packet_rx_queue, (void*)&msg, 0); + return; +} + +/** \brief Low level init of the MAC and PHY. + * + * \param[in] netif Pointer to LWIP netif structure + */ + +static err_t low_level_init(struct netif *netif) +{ + static int init_flag = 0; + if (init_flag == 0) { + wland_reg_func(); + init_flag = 1; + } + return ERR_OK; +} + +/** + * This function is the ethernet packet send function. It calls + * etharp_output after checking link status. + * + * \param[in] netif the lwip network interface structure for this enetif + * \param[in] q Pointer to pbug to send + * \param[in] ipaddr IP address + * \return ERR_OK or error code + */ +err_t rda91h_etharp_output(struct netif *netif, struct pbuf *q, const ip_addr_t *ipaddr) +{ + /* Only send packet is link is up */ + if (netif->flags & NETIF_FLAG_LINK_UP) + return etharp_output(netif, q, ipaddr); + + return ERR_CONN; +} + +/** \brief Low level output of a packet. Never call this from an + * interrupt context, as it may block until TX descriptors + * become available. + * + * \param[in] netif the lwip network interface structure for this netif + * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) + * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent + */ +static err_t rda91h_low_level_output(struct netif *netif, struct pbuf *p) +{ + struct pbuf *q; + + /* rda5996 initiate transfer */ + u32_t actual_txlen = 0; + u8_t **data; + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + data = (void*)wland_get_databuf(); + + if(data == NULL){ + LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); + return ERR_BUF; + } + + for(q = p; q != NULL; q = q->next) + { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + MEMCPY(&((*data)[actual_txlen+2]), q->payload, q->len);//reserve wid header length + actual_txlen += q->len; + if(actual_txlen > 1514 || actual_txlen > p->tot_len) + { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", + actual_txlen, p->tot_len)); + return ERR_BUF; + } + } + + /* Signal rda5996 that packet should be sent */ + if(actual_txlen == p->tot_len) + { + if(netif->name[0] == 's' && netif->name[1] == 't') { + wland_txip_data((void*)data, actual_txlen, 0); + } else if(netif->name[0] == 'a' && netif->name[1] == 'p') { + wland_txip_data((void*)data, actual_txlen, 1); + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; + } + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", + actual_txlen, p->tot_len)); + + + return ERR_BUF; +} + +/** + * Should be called at the beginning of the program to set up the + * network interface. + * + * This function should be passed as a parameter to netif_add(). + * + * @param[in] netif the lwip network interface structure for this netif + * @return ERR_OK if the loopif is initialized + * ERR_MEM if private data couldn't be allocated + * any other err_t on error + */ +err_t wifi_arch_enetif_init(struct netif *netif) +{ + err_t err; + static int thread_init_flag = 0; + LWIP_ASSERT("netif != NULL", (netif != NULL)); + + if (*((int *)netif->state) == 0) { + r91h_wifidata.netif_sta = netif; + netif->name[0] = 's'; + netif->name[1] = 't'; +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->hostname == NULL) + netif->hostname = "lwipr91h_sta"; +#endif /* LWIP_NETIF_HOSTNAME */ + rda_get_macaddr((u8_t *)(netif->hwaddr), 0); + } else if(*((int *)netif->state) == 1) { + r91h_wifidata.netif_ap = netif; + netif->name[0] = 'a'; + netif->name[1] = 'p'; +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + if(netif->hostname == NULL) + netif->hostname = "lwipr91h_ap"; +#endif /* LWIP_NETIF_HOSTNAME */ + rda_get_macaddr((u8_t *)(netif->hwaddr), 1); + } + + netif->hwaddr_len = ETHARP_HWADDR_LEN; + + /* maximum transfer unit */ + netif->mtu = 1500; + + /* device capabilities */ + // TODOETH: check if the flags are correct below + netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; + + /* Initialize the hardware */ + netif->state = &r91h_wifidata; + err = low_level_init(netif); + if (err != ERR_OK) + return err; + + netif->output = rda91h_etharp_output; + netif->linkoutput = rda91h_low_level_output; + if(thread_init_flag == 0){ + /* PHY monitoring task */ + sys_thread_new("maclib_thread", maclib_task, netif->state, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); + sys_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + thread_init_flag = 1; + } + return ERR_OK; +} + +unsigned char rda_mac_addr[6] = "\0"; +static int is_available_mac_addr(unsigned char *mac_addr) +{ + if (mac_addr[0]==0 && mac_addr[1]==0 && mac_addr[2]==0 && + mac_addr[3]==0 && mac_addr[4]==0 && mac_addr[5]==0) + return 0; + if (mac_addr[0]&0x1) + return 0; + return 1; +} +static void rda_get_macaddr_from_flash(unsigned char *macaddr) +{ + int ret; + if (!mac_is_valid((char *)rda_mac_addr)) { + ret = rda5981_flash_read_mac_addr(rda_mac_addr); + if ((ret!=0) || (is_available_mac_addr(rda_mac_addr)==0)) { +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + unsigned int out_len; + ret = mbedtls_hardware_poll(NULL, rda_mac_addr, 6, &out_len); + if (6 != out_len) { + LWIP_DEBUGF(NETIF_DEBUG, ("out_len err:%d\n", out_len)); + } +#else + ret = rda_trng_get_bytes(rda_mac_addr, 6); +#endif + rda_mac_addr[0] &= 0xfe; /* clear multicast bit */ + rda_mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ + rda5981_flash_write_mac_addr(rda_mac_addr); + } + } + memcpy(macaddr, rda_mac_addr, 6); +} +void mbed_mac_address(char *mac) +{ + mac[0] = 0xD6; + mac[1] = 0x71; + mac[2] = 0x36; + mac[3] = 0x60; + mac[4] = 0xD8; +#if !MBED_CONF_APP_ECHO_SERVER + mac[5] = 0xF4; +#else + mac[5] = 0xF3; +#endif + return; +} diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c new file mode 100644 index 0000000..07781ff --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c @@ -0,0 +1,453 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if 1 +#include "sys_arch.h" +#include "cmsis_os.h" +#include "cmsis_os2.h" +#include "lwip/sys.h" +#include "rtx_lib.h" + +#include +#include +#include "mbed_assert.h" +#define NO_ERR 0 +#define ERR -1 + +//#define RDA_SYS_DEBUG +#ifdef RDA_SYS_DEBUG +#define RDA_SYS_PRINT(fmt, ...) do {\ + printf(fmt, ##__VA_ARGS__);\ + } while (0) +#else +#define RDA_SYS_PRINT(fmt, ...) +#endif + + +/* Alarm */ +// Timer definitions +#define osTimerInvalid 0 +#define osTimerStopped 1 +#define osTimerRunning 2 +#if 0 +// Timer structures, same as os_timer_cb(rt_CMSIS.c) +typedef struct rda_ostmr_cb { + struct rda_ostmr_cb *next; // Pointer to next active Timer + uint8_t state; // Timer State + uint8_t type; // Timer Type (Periodic/One-shot) + uint16_t reserved; // Reserved + uint32_t tcnt; // Timer Delay Count + uint32_t icnt; // Timer Initial Count + void *arg; // Timer Function Argument + const osTimerDef_t *timer; // Pointer to Timer definition +} rda_ostmr_cb_t; +#endif +//#define USING_STDLIB + +#if !defined(USING_STDLIB) +typedef struct rda_tmr_node { + mbed_rtos_storage_timer_t _obj_mem; +} rda_tmr_node_t; + +typedef struct rda_tmr_ctrl { + unsigned char *buff; + unsigned char *state; + unsigned char max_node_num; + unsigned char node_size; + unsigned char node_cntr; + unsigned char last_freed_node_idx; +} rda_tmr_ctrl_t; + +#define MAX_ALARM_NUM (28) +#define WORD_ALIGN(n) (((n) + 0x03UL) & ~0x03UL) +#define MAX_ALARM_STAT_SIZE WORD_ALIGN(MAX_ALARM_NUM >> 3) +#define MAX_ALARM_MEM_SIZE (MAX_ALARM_NUM * WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)) + MAX_ALARM_STAT_SIZE) + +unsigned long g_alarm_buf[WORD_ALIGN(MAX_ALARM_MEM_SIZE) >> 2] = {0}; +rda_tmr_ctrl_t g_alarm_ctrl = { + (unsigned char *)g_alarm_buf + MAX_ALARM_STAT_SIZE, + (unsigned char *)g_alarm_buf, + MAX_ALARM_NUM, + WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)), + 0U, + 0U +}; + +__STATIC_INLINE unsigned char get_node_state(unsigned char *buf, unsigned char idx) +{ + unsigned char state, ofst; + ofst = (idx & 0x07U); + buf += (idx >> 3); + state = (*buf >> ofst) & 0x01U; + return state; +} + +__STATIC_INLINE void set_node_state(unsigned char *buf, unsigned char idx, unsigned char state) +{ + unsigned char ofst, tmp; + ofst = (idx & 0x07U); + buf += (idx >> 3); + tmp = *buf & (~(0x01U << ofst)); + *buf = tmp | (((state & 0x01U) << ofst)); +} + +static rda_tmr_node_t *get_tmr_node(void) +{ + rda_tmr_node_t *node = NULL; + unsigned char idx = g_alarm_ctrl.last_freed_node_idx; + if ((idx < g_alarm_ctrl.max_node_num) && (0U == get_node_state(g_alarm_ctrl.state, idx))) { + set_node_state(g_alarm_ctrl.state, idx, 1U); + node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); + g_alarm_ctrl.node_cntr++; + } else { + for (idx = 0U; idx < g_alarm_ctrl.max_node_num; idx++) { + if(0U == get_node_state(g_alarm_ctrl.state, idx)) { + set_node_state(g_alarm_ctrl.state, idx, 1U); + node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); + g_alarm_ctrl.node_cntr++; + break; + } + } + } + return node; +} + +static void put_tmr_node(rda_tmr_node_t *node) +{ + unsigned char *node_buf = (unsigned char *)node; + unsigned char idx = (node_buf - g_alarm_ctrl.buff) / g_alarm_ctrl.node_size; + if ((node_buf > g_alarm_ctrl.buff) && (idx < g_alarm_ctrl.max_node_num) && + (1U == get_node_state(g_alarm_ctrl.state, idx))) { + set_node_state(g_alarm_ctrl.state, idx, 0U); + g_alarm_ctrl.node_cntr--; + g_alarm_ctrl.last_freed_node_idx = idx; + } +} +#endif /* !USING_STDLIB */ + +/** + * @brief : get current time in units of micro second + * @param[in] : + * @param[out]: + * @return : return time value with uint32 type + */ +unsigned long rda_get_cur_time_ms(void) +{ + return sys_now(); +} + +/** + * @brief : create an alarm with given function, return timer handle + * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) + * @param[out]: + * @return : return timer handle, a pointer to the timer structure, non-zero is valid + */ +void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode) +{ + osTimerId_t handle; + mbed_rtos_storage_timer_t* _obj_mem = NULL; + MBED_ASSERT(func != NULL); + osTimerAttr_t attr = { 0 }; +#if defined(USING_STDLIB) + _obj_mem = (mbed_rtos_storage_timer_t*)malloc(sizeof(mbed_rtos_storage_timer_t)); +#else /* USING_STDLIB */ + _obj_mem = (mbed_rtos_storage_timer_t*)get_tmr_node(); +#endif /* USING_STDLIB */ + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(_obj_mem)); + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_timer_t); + //printf("hehehehe fun %p\r\n", func); + handle = osTimerNew((osTimerFunc_t)func, mode, (void *)data, &attr); + //printf("time cb %p handle %p\r\n", _obj_mem, handle); + MBED_ASSERT(handle != NULL); + return handle; +} + +void * rda_alarm_create(void *func, unsigned int data) +{ + return rda_alarm_create_v2(func, data, osTimerOnce); +} + +/** + * @brief : delete an alarm with given handle, then reset the handle + * @param[in] : *handle(pointer to the timer structure) + * @param[out]: **handle(address of the handle variable) + * @return : + */ +int rda_alarm_delete(void **handle) +{ + if (NULL != *handle) { + osTimerId timer_id = (osTimerId)(*handle); + osStatus retval = osTimerDelete(timer_id); + if (osOK == retval) { +#if defined(USING_STDLIB) + free(timer_id); +#else /* USING_STDLIB */ + put_tmr_node((rda_tmr_node_t *)timer_id); +#endif /* USING_STDLIB */ + *handle = NULL; + } else { + RDA_SYS_PRINT("Delete alarm error: %d\r\n", retval); + return ERR; + } + return NO_ERR; + } + return ERR; +} + +/** + * @brief : start an alarm, raise a function call after given timeout delay + * @param[in] : handle(pointer to the timer structure)/timeout(micro second) + * @param[out]: + * @return : + */ +int rda_alarm_start(void *handle, unsigned int timeout_ms) +{ + if (NULL != handle) { + osTimerId timer_id = (osTimerId)handle; + osStatus retval = osTimerStart(timer_id, (uint32_t)timeout_ms); + if (osOK != retval) { + RDA_SYS_PRINT("Start alarm error: %d\r\n", retval); + return ERR; + } + return NO_ERR; + } + return ERR; +} + +/** + * @brief : stop an alarm, will not raise a function call any more + * @param[in] : handle(pointer to the timer structure) + * @param[out]: + * @return : + */ +int rda_alarm_stop(void *handle) +{ + if (NULL != handle) { + osTimerId timer_id = (osTimerId)handle; + os_timer_t *timer = osRtxTimerId(timer_id); + if(timer->state == osRtxTimerRunning){ + osStatus retval = osTimerStop(timer_id); + if(osOK != retval) { + RDA_SYS_PRINT("Stop alarm error: %d\r\n", retval); + return ERR; + } + } + return NO_ERR; + } + return ERR; +} + + + +/* Semaphore */ +void* rda_sem_create(unsigned int count) +{ + osSemaphoreId_t sem; + mbed_rtos_storage_semaphore_t *_obj_mem = (mbed_rtos_storage_semaphore_t*)malloc(sizeof(mbed_rtos_storage_semaphore_t)); + osSemaphoreAttr_t attr = { 0 }; + attr.name = "rda_unnamed_sem"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_semaphore_t); + sem = osSemaphoreNew(1, count, &attr); + MBED_ASSERT(sem != NULL); + + return (void*)sem; +} + +int rda_sem_wait(void* sem, unsigned int millisec) +{ + int res; + + res = osSemaphoreWait(sem, millisec); + if (res > 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_wait error %d\r\n", res); + return ERR; + } +} + +int rda_sem_release(void *sem) +{ + int res; + + res = osSemaphoreRelease(sem); + if (res == 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_release error %d\r\n", res); + return ERR; + } +} + +int rda_sem_delete(void *sem) +{ + int res; + + res = osSemaphoreDelete(sem); + free(sem); + if (res == 0) { + return NO_ERR; + } else { + RDA_SYS_PRINT("rda_sem_delete error %d\r\n", res); + return ERR; + } +} + +/* Mail */ +void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize) +{ + unsigned int mq_size = msgcnt * (msgsize + sizeof(os_message_t)); + osMessageQueueId_t msgq; + mbed_rtos_storage_msg_queue_t *_obj_mem = (mbed_rtos_storage_msg_queue_t*)malloc(sizeof(mbed_rtos_storage_msg_queue_t)); + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_msg_queue_t)); + void *_mq_mem = (void *)malloc(mq_size); + MBED_ASSERT(_mq_mem != NULL); + memset(_mq_mem, 0, mq_size); + osMessageQueueAttr_t attr = { 0 }; + attr.name = "rda_unnamed_message_queue"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_msg_queue_t); + attr.mq_mem = _mq_mem; + attr.mq_size = mq_size; + msgq = osMessageQueueNew(msgcnt, msgsize, &attr); + MBED_ASSERT(msgq != NULL); + + return (void*)msgq; +} + +int rda_mail_get(void *msgq, void *msg, unsigned int wait) +{ + int ret; + ret = osMessageQueueGet(msgq, msg, 0, wait); + return ret; +} + +int rda_mail_put(void *msgq, void *msg, unsigned int wait) +{ + int ret; + ret = osMessageQueuePut(msgq, msg, 0, wait); + return ret; +} + +/* Mutex */ +void* rda_mutex_create(void) +{ + osMutexId_t rdamutex; + osMutexAttr_t attr = { 0 }; + mbed_rtos_storage_mutex_t *_obj_mem = (mbed_rtos_storage_mutex_t *)malloc(sizeof(mbed_rtos_storage_mutex_t)); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_mutex_t)); + attr.name = "rda_unnamed_mutex"; + attr.cb_mem = _obj_mem; + attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); + attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; + rdamutex = osMutexNew(&attr); + MBED_ASSERT(rdamutex != NULL); + return (void *)rdamutex; +} + +int rda_mutex_wait(void *rdamutex, unsigned int millisec) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexWait(mutex, millisec); + if (res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +int rda_mutex_realease(void *rdamutex) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexRelease(mutex); + if(res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +int rda_mutex_delete(void *rdamutex) +{ + osMutexId_t mutex = (osMutexId_t)rdamutex; + osStatus res; + res = osMutexDelete(mutex); + free(mutex); + if (res == osOK) { + return NO_ERR; + } else { + return ERR; + } +} + +/* Thread */ +void* rda_thread_new(const char *pcName, + void (*thread)(void *arg), + void *arg, int stacksize, int priority) +{ + osThreadId_t id; + osThreadAttr_t _attr = { 0 }; + mbed_rtos_storage_thread_t *_obj_mem = (mbed_rtos_storage_thread_t *)malloc(sizeof(mbed_rtos_storage_thread_t)); + MBED_ASSERT(_obj_mem != NULL); + memset(_obj_mem, 0, sizeof(mbed_rtos_storage_thread_t)); + _attr.priority = priority; + _attr.stack_size = stacksize; + _attr.name = pcName ? pcName : "rda_unnamed_thread"; + _attr.stack_mem = malloc(stacksize); + MBED_ASSERT(_attr.stack_mem != NULL); + _attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + _attr.cb_mem = _obj_mem; + _attr.tz_module = 0; + + //Fill the stack with a magic word for maximum usage checking + for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) { + ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5; + } + id = osThreadNew(thread, arg, &_attr); + if (id == NULL){ + free(_attr.stack_mem); + free(_attr.cb_mem); + RDA_SYS_PRINT("sys_thread_new create error\n"); + return NULL; + } + return (void *)id; +} + +int rda_thread_delete(void* id) +{ + osStatus ret; + unsigned int *stk = ((osRtxThread_t *)id)->stack_mem; + ret = osThreadTerminate(id); + free(id); + free(stk); + if (ret != osOK) { + return ERR; + } + return NO_ERR; +} + +void* rda_thread_get_id(void) +{ + osThreadId id = osThreadGetId(); + return (void*)id; +} +#endif diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c new file mode 100644 index 0000000..a2c0cd8 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c @@ -0,0 +1,1481 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "critical.h" +#include "wland_flash.h" +#include "wland_dbg.h" +#include "rda5981_flash.h" +#include "wland_flash_wp.h" + +#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] + +u32 flash_size = FLASH_SIZE; +static u32 user_data_location = RDA5991H_USER_DATA_ADDR; +static u32 third_parter_data_location = RDA5991H_3RDPARTER_DATA_ADDR; +static u32 third_parter_data_len = RDA5991H_3RDPARTER_DATA_LEN; +int rda5981_read_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + char *temp_buf = NULL, *temp_buf_aligned; + + addr &= (flash_size -1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't read system data\n"); + return -1; + } + + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + ret = -1; + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + } else { + temp_buf_aligned = buf; + } + + core_util_critical_section_enter(); + spi_flash_flush_cache(); + SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + + if (temp_buf_aligned != buf) { + memcpy(buf, temp_buf_aligned, len); + } + +out: + if (temp_buf) { + free(temp_buf); + } + + return ret; +} + +void rda5981_spi_flash_erase_64KB_block(u32 addr) +{ + if (rda_ccfg_hwver() < 4) { + spi_wip_reset_2(); + spi_write_reset_2(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); + wait_busy_down_2(); + spi_wip_reset_2(); + } else { + spi_wip_reset_4(); + spi_write_reset_4(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); + wait_busy_down_4(); + spi_wip_reset_4(); + } +} +void rda5981_spi_erase_partition(void *src, u32 counts) +{ + u32 a4k, a64k, a64kend, a4kend, atmp; + + if (counts > 0x00) { + a4k = ((u32)src ) & (~((0x01UL << 12) - 0x01UL)); + a64k = ((u32)src + (0x01UL << 16) - 0x01UL) & (~((0x01UL << 16) - 0x01UL)); + a64kend = ((u32)src + counts ) & (~((0x01UL << 16) - 0x01UL)); + a4kend = ((u32)src + counts + (0x01UL << 12) - 0x01UL) & (~((0x01UL << 12) - 0x01UL)); + + for (atmp = a4k; atmp < a4kend; atmp += (0x01UL << 12)) { + if (a64kend > a64k) { + if (atmp == a64k) { + for (; atmp < a64kend; atmp += (0x01UL << 16)) { + core_util_critical_section_enter(); + rda5981_spi_flash_erase_64KB_block(atmp); + core_util_critical_section_exit(); + } + if (atmp == a4kend) { + break; + } + } + } + core_util_critical_section_enter(); + rda5981_spi_flash_erase_4KB_sector(atmp); + core_util_critical_section_exit(); + } + } +} +//@len must be 4k aligment +int rda5981_erase_flash(u32 addr, u32 len) +{ + WLAND_DBG(INFO, "erase flash :%x:%x\n", addr, len); + + addr &= (flash_size - 1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't erase system data\n"); + return -1; + } + + if (len & (SECTOR_SIZE-1)) { + len = ((len+SECTOR_SIZE) & (~(SECTOR_SIZE-1))); + } + flash_wrtie_protect(addr); + rda5981_spi_erase_partition((void*)addr, len); + flash_wrtie_protect_all(); + return 0; +} + +//@len must be 256 aligment +int rda5981_write_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + u8 *temp_buf = NULL, *temp_buf_aligned; + u8 *check_buf = NULL; + + addr &= (flash_size -1); + if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { + WLAND_DBG(ERROR, "couldn't write system data\n"); + return -1; + } + + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + memcpy(temp_buf_aligned, buf, len); + } else { + temp_buf_aligned = (u8*)buf; + } + flash_wrtie_protect(addr); + core_util_critical_section_enter(); + //RDA5991H_ERASE_FLASH(addr, len); + RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + flash_wrtie_protect_all(); + +#ifdef FLASH_READ_CHECK + if (ret == 0) { + check_buf = malloc(len); + rda5981_read_flash(addr, check_buf, len); + if (memcmp(buf, check_buf, len) == 0) { + ret = 0; + } else { + ret = -1; + } + } +#endif /*FLASH_READ_CHECK*/ + +out: + if (temp_buf) { + free(temp_buf); + } + if (check_buf) { + free(check_buf); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +rda5991h_user_data wland_user_data; +u8 read_flag = 0; +int rda5981_write_user_data(u8 *data, u16 len, u32 flag) +{ + WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || + strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + memset(&wland_user_data, 0xff, sizeof(wland_user_data)); + wland_user_data.flag = flag; + strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); + } + + wland_user_data.flag |= flag; + + switch (flag) { + case RDA5991H_USER_DATA_FLAG_STA: + memcpy(&wland_user_data.sta_data, data, + min(sizeof(wland_user_data.sta_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_MAC: + memcpy(wland_user_data.mac_addr, data, + min(sizeof(wland_user_data.mac_addr), len)); + break; + case RDA5991H_USER_DATA_FLAG_PMK: + memcpy(wland_user_data.pmk, data, + min(sizeof(wland_user_data.pmk), len)); + break; + case RDA5991H_USER_DATA_FLAG_IP: + memcpy(wland_user_data.ip, data, + min(RDA5991H_USER_DATA_IP_LENGTH, len)); + break; + case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: + memcpy(&wland_user_data.parter_data_len, data, + min(sizeof(wland_user_data.parter_data_len), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER: + memcpy(&wland_user_data.tx_power, data, + min(sizeof(wland_user_data.tx_power), len)); + break; + case RDA5991H_USER_DATA_FLAG_XTAL_CAL: + memcpy(&wland_user_data.xtal_cal, data, + min(sizeof(wland_user_data.xtal_cal), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: + memcpy(&wland_user_data.tx_power_rf, data, + min(sizeof(wland_user_data.tx_power_rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: + memcpy(&wland_user_data.tx_power_phy_gn, data, + min(sizeof(wland_user_data.tx_power_phy_gn), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: + memcpy(&wland_user_data.tx_power_phy_b, data, + min(sizeof(wland_user_data.tx_power_phy_b), len)); + break; + case RDA5991H_USER_DATA_FLAG_AP: + memcpy(&wland_user_data.ap_data, data, + min(sizeof(wland_user_data.ap_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_APNET: + memcpy(&wland_user_data.ap_net_data, data, + min(sizeof(wland_user_data.ap_net_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_DHCP: + memcpy(&wland_user_data.dhcp, data, + min(sizeof(wland_user_data.dhcp), len)); + break; + case RDA5991H_USER_DATA_FLAG_UART: + memcpy(&wland_user_data.uart, data, + min(sizeof(wland_user_data.uart), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF: + memcpy(&wland_user_data.rf, data, + min(sizeof(wland_user_data.rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + memcpy(&wland_user_data.rf_channels, data, + min(sizeof(wland_user_data.rf_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY: + memcpy(&wland_user_data.phy, data, + min(sizeof(wland_user_data.phy), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + memcpy(&wland_user_data.phy_channels, data, + min(sizeof(wland_user_data.phy_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: + memcpy(&wland_user_data.tp_offset, data, + min(sizeof(wland_user_data.tp_offset), len)); + break; + default: + return -1; + } + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_erase_user_data(u32 flag) +{ + if (!read_flag) { + read_flag = 1; + rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + + if ((wland_user_data.flag & flag) == 0) { + return 0; + } + + wland_user_data.flag &= (~flag); + + if (wland_user_data.flag == 0) { + wland_user_data.flag = RDA5991H_USER_DATA_FLAG_UNINITIALIZED; + } + if (flag & RDA5991H_USER_DATA_FLAG_STA) { + memset(&wland_user_data.sta_data, 0xff, + sizeof(wland_user_data.sta_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_MAC) { + memset(wland_user_data.mac_addr, 0xff, + sizeof(wland_user_data.mac_addr)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PMK) { + memset(wland_user_data.pmk, 0xff, + sizeof(wland_user_data.pmk)); + } + if (flag & RDA5991H_USER_DATA_FLAG_IP) { + memset(wland_user_data.ip, 0xff, + RDA5991H_USER_DATA_IP_LENGTH); + } + if (flag & RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN) { + memset(&wland_user_data.parter_data_len, 0xff, + sizeof(wland_user_data.parter_data_len)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER) { + memset(&wland_user_data.tx_power, 0xff, + sizeof(wland_user_data.tx_power)); + } + if (flag & RDA5991H_USER_DATA_FLAG_XTAL_CAL) { + memset(&wland_user_data.xtal_cal, 0xff, + sizeof(wland_user_data.xtal_cal)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_RF) { + memset(&wland_user_data.tx_power_rf, 0xff, + sizeof(wland_user_data.tx_power_rf)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN) { + memset(&wland_user_data.tx_power_phy_gn, 0xff, + sizeof(wland_user_data.tx_power_phy_gn)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B) { + memset(&wland_user_data.tx_power_phy_b, 0xff, + sizeof(wland_user_data.tx_power_phy_b)); + } + if (flag & RDA5991H_USER_DATA_FLAG_AP) { + memset(&wland_user_data.ap_data, 0xff, + sizeof(wland_user_data.ap_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_APNET) { + memset(&wland_user_data.ap_net_data, 0xff, + sizeof(wland_user_data.ap_net_data)); + } + if (flag & RDA5991H_USER_DATA_FLAG_DHCP) { + memset(&wland_user_data.dhcp, 0xff, + sizeof(wland_user_data.dhcp)); + } + if (flag & RDA5991H_USER_DATA_FLAG_UART) { + memset(&wland_user_data.uart, 0xff, + sizeof(wland_user_data.uart)); + } + if (flag & RDA5991H_USER_DATA_FLAG_RF) { + memset(&wland_user_data.rf, 0xff, + sizeof(wland_user_data.rf)); + } + if (flag & RDA5991H_USER_DATA_FLAG_RF_CHANNELS) { + memset(&wland_user_data.rf_channels, 0xff, + sizeof(wland_user_data.rf_channels)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PHY) { + memset(&wland_user_data.phy, 0xff, + sizeof(wland_user_data.phy)); + } + if (flag & RDA5991H_USER_DATA_FLAG_PHY_CHANNELS) { + memset(&wland_user_data.phy_channels, 0xff, + sizeof(wland_user_data.phy_channels)); + } + if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET) { + memset(&wland_user_data.tp_offset, 0xff, + sizeof(wland_user_data.tp_offset)); + } + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_read_user_data(u8 *data, u16 len, u32 flag) +{ + //rda5991h_user_data wland_user_data; + WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); + + if (!read_flag) { + read_flag = 1; + rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + return -2; + } + if ((wland_user_data.flag & flag) == 0) { + return -3; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_STA: + memcpy(data, &wland_user_data.sta_data, + min(sizeof(wland_user_data.sta_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_MAC: + memcpy(data, wland_user_data.mac_addr, + min(sizeof(wland_user_data.mac_addr), len)); + break; + case RDA5991H_USER_DATA_FLAG_PMK: + memcpy(data, wland_user_data.pmk, + min(sizeof(wland_user_data.pmk), len)); + break; + case RDA5991H_USER_DATA_FLAG_IP: + memcpy(data, wland_user_data.ip, + min(RDA5991H_USER_DATA_IP_LENGTH, len)); + break; + case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: + memcpy(data, &wland_user_data.parter_data_len, + min(sizeof(wland_user_data.parter_data_len), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER: + memcpy(data, &wland_user_data.tx_power, + min(sizeof(wland_user_data.tx_power), len)); + break; + case RDA5991H_USER_DATA_FLAG_XTAL_CAL: + memcpy(data, &wland_user_data.xtal_cal, + min(sizeof(wland_user_data.xtal_cal), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: + memcpy(data, &wland_user_data.tx_power_rf, + min(sizeof(wland_user_data.tx_power_rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: + memcpy(data, &wland_user_data.tx_power_phy_gn, + min(sizeof(wland_user_data.tx_power_phy_gn), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: + memcpy(data, &wland_user_data.tx_power_phy_b, + min(sizeof(wland_user_data.tx_power_phy_b), len)); + break; + case RDA5991H_USER_DATA_FLAG_AP: + memcpy(data, &wland_user_data.ap_data, + min(sizeof(wland_user_data.ap_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_APNET: + memcpy(data, &wland_user_data.ap_net_data, + min(sizeof(wland_user_data.ap_net_data), len)); + break; + case RDA5991H_USER_DATA_FLAG_DHCP: + memcpy(data, &wland_user_data.dhcp, + min(sizeof(wland_user_data.dhcp), len)); + break; + case RDA5991H_USER_DATA_FLAG_UART: + memcpy(data, &wland_user_data.uart, + min(sizeof(wland_user_data.uart), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF: + memcpy(data, &wland_user_data.rf, + min(sizeof(wland_user_data.rf), len)); + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + memcpy(data, &wland_user_data.rf_channels, + min(sizeof(wland_user_data.rf_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY: + memcpy(data, &wland_user_data.phy, + min(sizeof(wland_user_data.phy), len)); + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + memcpy(data, &wland_user_data.phy_channels, + min(sizeof(wland_user_data.phy_channels), len)); + break; + case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: + memcpy(data, &wland_user_data.tp_offset, + min(sizeof(wland_user_data.tp_offset), len)); + break; + default: + return -1; + } + return 0; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_mac_addr(u8 *mac_addr) +{ + int ret; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); + if (ret) { + WLAND_DBG(ERROR, "read mac addr from flash fail\r\n"); + } else { + WLAND_DBG(INFO, "Done(ret:%d)"MACDBG"\r\n", ret, MAC2STRDBG(mac_addr)); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_mac_addr(u8 *mac_addr) +{ + WLAND_DBG(INFO, "Enter"MACDBG"\r\n", MAC2STRDBG(mac_addr)); + return rda5981_write_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_uart(void) +{ + return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_UART); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_uart(u32 *uart) +{ + int ret; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); + if (ret) { + WLAND_DBG(ERROR, "read uart setting from flash fail\r\n"); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_uart(u32 *uart) +{ + return rda5981_write_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_sta_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK | + RDA5991H_USER_DATA_FLAG_STA); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_sta_data(char *ssid, char *passwd) +{ + int ret; + wland_sta_data_t sta_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); + if (ret == 0) { + strcpy(ssid, sta_data.ssid); + strcpy(passwd, sta_data.key); + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +extern u8 *rda_get_bssinfo_pmk(void); +extern u8 *rda_get_bssinfo_SSID(void); +int rda5981_flash_write_sta_data(const char *ssid, const char *passwd) +{ + int ret = 0, ret1; + wland_sta_data_t sta_data; + u8 *pbss_info_pmk = NULL, *pbss_info_SSID = NULL; + pbss_info_pmk = rda_get_bssinfo_pmk(); + pbss_info_SSID = rda_get_bssinfo_SSID(); + + WLAND_DBG(INFO, "Enter:ssid:%s,pw:%s, pmk:%02x %02x***\r\n", + ssid, passwd, pbss_info_pmk[0], pbss_info_SSID[1]); + if (strlen(ssid) == 0) { + WLAND_DBG(ERROR, "ssid is NULL\n"); + return -1; + } + + memset(&sta_data, 0xff, sizeof(sta_data)); + strcpy(sta_data.ssid, ssid); + strcpy(sta_data.key, passwd); + if (pbss_info_pmk[0] && memcmp(pbss_info_SSID, ssid, 6)==0) { + ret = rda5981_write_user_data(pbss_info_pmk, sizeof(pbss_info_pmk), RDA5991H_USER_DATA_FLAG_PMK); + } + ret1 = rda5981_write_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); + return ret || ret1;; +} + + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_dhcp_data(void) +{ + int ret;//, ret1; + //WLAND_DBG(INFO, "Enter\r\n"); + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_DHCP); + //ret1 = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_dhcp_data(unsigned int *fixip, unsigned int *ip, unsigned int *msk, unsigned int *gw) +{ + int ret; + wland_dhcp_t dhcp; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); + if (ret == 0) { + *fixip = dhcp.fixip; + *ip = dhcp.ip; + *msk = dhcp.msk; + *gw = dhcp.gw; + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_dhcp_data(unsigned int fixip, unsigned int ip, unsigned int msk, unsigned int gw) +{ + int ret = 0; + wland_dhcp_t dhcp; + + memset(&dhcp, 0xff, sizeof(dhcp)); + dhcp.fixip = fixip; + dhcp.ip = ip; + dhcp.msk = msk; + dhcp.gw = gw; + ret = rda5981_write_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); + return ret; +} + + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_ap_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_AP); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel) +{ + int ret = 0; + wland_ap_data_t ap_data; + + if (strlen(ssid) == 0) { + WLAND_DBG(ERROR, "ssid is NULL\n"); + return -1; + } + + memset(&ap_data, 0xff, sizeof(ap_data)); + strcpy(ap_data.ssid, ssid); + strcpy(ap_data.key, passwd); + ap_data.channel = channel; + ret = rda5981_write_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel) +{ + int ret; + wland_ap_data_t ap_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); + if (ret == 0) { + strcpy(ssid, ap_data.ssid); + strcpy(passwd, ap_data.key); + *channel = ap_data.channel; + } + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_erase_ap_net_data(void) +{ + int ret; + ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_APNET); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, + unsigned int dhcps, unsigned int dhcpe) +{ + int ret = 0; + wland_ap_net_data_t ap_net_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + memset(&ap_net_data, 0xff, sizeof(ap_net_data)); + ap_net_data.ip = ip; + ap_net_data.msk = msk; + ap_net_data.gw = gw; + ap_net_data.dhcps = dhcps; + ap_net_data.dhcpe = dhcpe; + + ret = rda5981_write_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); + return ret; +} + +/* + * return 0:ok, else:error. + */ +int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, + unsigned int *dhcps, unsigned int *dhcpe) +{ + int ret = 0; + wland_ap_net_data_t ap_net_data; + + WLAND_DBG(INFO, "Enter\r\n"); + + ret = rda5981_read_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); + if (ret == 0) { + *ip = ap_net_data.ip; + *msk = ap_net_data.msk; + *gw = ap_net_data.gw; + *dhcps = ap_net_data.dhcps; + *dhcpe = ap_net_data.dhcpe; + } + return ret; +} + + +int rda5981_flash_read_pmk(u8 *pmk) +{ + WLAND_DBG(INFO, "Enter\r\n"); + return rda5981_read_user_data(pmk, 32, RDA5991H_USER_DATA_FLAG_PMK); +} + +int rda5981_flash_read_ip_addr(u8 *ip_addr, u8 *server_addr) +{ + int ret; + u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; + WLAND_DBG(DEBUG, "Enter\r\n"); + ret = rda5981_read_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); + if (ret) { + WLAND_DBG(ERROR, "read ip addr from flash fail\r\n"); + } else { + memcpy(ip_addr, buf, 4); + memcpy(server_addr, buf+4, 4); + WLAND_DBG(INFO, "read ip:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + } + return ret; +} + +int rda5981_flash_write_ip_addr(u8 *ip_addr, u8 *server_addr) +{ + u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; + WLAND_DBG(INFO, "write:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); + memcpy(buf, ip_addr, 4); + memcpy(buf+4, server_addr, 4); + return rda5981_write_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); +} + +int rda5981_flash_read_3rdparter_data_length() +{ + int ret; + u32 data_len = 0; + + WLAND_DBG(INFO, "Enter\r\n"); + ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); + return -1; + } + return data_len; +} + +int rda5981_flash_read_3rdparter_data(u8 *buf, u32 buf_len) +{ + int ret; + u32 data_len = 0; + + WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); + ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); + return -1; + } + + if (buf_len < data_len) + WLAND_DBG(ERROR, "The buf you prepared is to small(%u:%u)\r\n", buf_len, data_len); + + data_len = min(buf_len, data_len); + + ret = rda5981_read_flash(third_parter_data_location, + (char *)(buf), data_len); + if (ret) { + WLAND_DBG(ERROR, "read parter data from flash fail(%d)\r\n", ret); + return -2; + } + + return data_len; +} + +int rda5981_flash_erase_3rdparter_data() +{ + return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); +} + +int rda5981_flash_write_3rdparter_data(const u8 *buf, u32 buf_len) +{ + int ret; + + WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); + if (buf_len > third_parter_data_len) { + WLAND_DBG(ERROR, "buf too long(%u), we have only %x flash space\r\n", + buf_len, third_parter_data_len); + return -1; + } + + rda5981_erase_flash(third_parter_data_location, buf_len); + ret = rda5981_write_flash(third_parter_data_location, + (char *)(buf), buf_len); + if (ret) { + WLAND_DBG(ERROR, "write parter data to flash fail\r\n"); + return -2; + } + + ret = rda5981_write_user_data((u8 *)(&buf_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); + if (ret) { + WLAND_DBG(ERROR, "write parter data length to flash fail\r\n"); + return -3; + } + return 0; +} + +int rda5981_set_flash_size(const u32 size) +{ + + WLAND_DBG(INFO, "Enter set flash size: %x\r\n", size); + if (size == 0x100000 || + size == 0x200000 || + size == 0x400000) { + flash_size = size; + return 0; + } + + return -1; +} + +int rda5981_set_user_data_addr(const u32 sys_data_addr, + const u32 user_data_addr, const u32 user_data_len) +{ + WLAND_DBG(INFO, "Enter set userdata addr: %x:%x:%x\r\n", + sys_data_addr, user_data_addr, user_data_len); + if ((sys_data_addr&(SECTOR_SIZE-1)) || (user_data_addr&(SECTOR_SIZE-1))) { + return -1; + } + if (sys_data_addr == user_data_addr) { + return -2; + } + + if (sys_data_addr<=0x18001000 || user_data_addr<=0x18001000) { + return -3; + } + if (sys_data_addr+0x1000 > 0x18000000+flash_size) { + return -4; + } + if (user_data_addr+user_data_len > 0x18000000+flash_size) { + return -5; + } + + user_data_location = sys_data_addr; + third_parter_data_location = user_data_addr; + third_parter_data_len= user_data_len; + return 0; +} + +int rda5981_write_user_data_regs(u8 *reg, u8 *value, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || + strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + memset(&wland_user_data, 0xff, sizeof(wland_user_data)); + wland_user_data.flag = flag; + strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); + } + + wland_user_data.flag |= flag; + + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + wland_user_data.rf.valid = 1; + wland_user_data.rf.flag = 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.rf.flag)) + return -2; + } + + if ((8 == idx) || (0 == wland_user_data.rf.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.rf.flag & BIT(idx))) { + wland_user_data.rf.reg_val[idx][0] = reg16; + wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); + wland_user_data.rf.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + wland_user_data.rf_channels.valid = 1; + wland_user_data.rf_channels.flag = 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.rf_channels.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.rf_channels.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.rf_channels.flag & BIT(idx))) { + wland_user_data.rf_channels.reg_val[idx][0] = reg16; + memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); + wland_user_data.rf_channels.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + wland_user_data.phy.valid = 1; + wland_user_data.phy.flag = 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.phy.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.phy.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.phy.flag & BIT(idx))) { + wland_user_data.phy.reg_val[idx][0] = reg32; + wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); + wland_user_data.phy.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + wland_user_data.phy_channels.valid = 1; + wland_user_data.phy_channels.flag = 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); + break; + } else { + continue; + } + } + if ((8 == idx) && (0xFF == wland_user_data.phy_channels.flag)) { + return -2; + } + } + + if ((8 == idx) || (0 == wland_user_data.phy_channels.flag)) { + for (idx = 0; idx < 8; idx++) { + if (!(wland_user_data.phy_channels.flag & BIT(idx))) { + wland_user_data.phy_channels.reg_val[idx][0] = reg32; + memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); + wland_user_data.phy_channels.flag |= BIT(idx); + break; + } else { + continue; + } + } + } + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + +int rda5981_erase_user_data_regs(u8 *reg, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if (0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if ((wland_user_data.flag & flag) == 0) { + return 0; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + return 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + memset(&wland_user_data.rf.reg_val[idx][0], 0xFF, 2 * sizeof(u16)); + wland_user_data.rf.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.rf.flag) { + wland_user_data.rf.valid = 0xFFFFFFFF; + wland_user_data.rf.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + return 0; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memset(&wland_user_data.rf_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u16)); + wland_user_data.rf_channels.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.rf_channels.flag) { + wland_user_data.rf_channels.valid = 0xFFFFFFFF; + wland_user_data.rf_channels.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + return 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + memset(&wland_user_data.phy.reg_val[idx][0], 0xFF, 2 * sizeof(u32)); + wland_user_data.phy.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.phy.flag) { + wland_user_data.phy.valid = 0xFFFFFFFF; + wland_user_data.phy.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + return 0; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memset(&wland_user_data.phy_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u32)); + wland_user_data.phy_channels.flag &= ~BIT(idx); + break; + } else { + continue; + } + } + } + + if (0 == wland_user_data.phy_channels.flag) { + wland_user_data.phy_channels.valid = 0xFFFFFFFF; + wland_user_data.phy_channels.flag = 0xFFFFFFFF; + wland_user_data.flag &= (~flag); + } + + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); + return rda5981_write_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data)); +} + + +int rda5981_read_user_data_regs(u8 *reg, u8 *value, u32 flag) +{ + u16 reg16 = 0; + u32 reg32 = 0; + u8 idx = 0; + + if (!read_flag) { + if(0 == rda5981_read_flash(user_data_location, + (char *)(&wland_user_data), sizeof(wland_user_data))) { + read_flag = 1; + } else { + return -1; + } + } + + if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff + return -1; + } + if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { + return -2; + } + if ((wland_user_data.flag & flag) == 0) { + return -3; + } + switch (flag) { + case RDA5991H_USER_DATA_FLAG_RF: + if (wland_user_data.rf.valid != 1) { + return -4; + } + + reg16 = *((u16 *)reg); + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf.flag & BIT(idx)) && + (wland_user_data.rf.reg_val[idx][0] == reg16)) { + memcpy(value, &wland_user_data.rf.reg_val[idx][1], sizeof(u16)); + break; + } else { + continue; + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: + if (wland_user_data.rf_channels.valid != 1) { + return -4; + } + + reg16 = *((u16 *)reg); + if (wland_user_data.rf_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.rf_channels.flag & BIT(idx)) && + (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { + memcpy(value, &wland_user_data.rf_channels.reg_val[idx][1], 14 * sizeof(u16)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_PHY: + if (wland_user_data.phy.valid != 1) { + return -4; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy.flag & BIT(idx)) && + (wland_user_data.phy.reg_val[idx][0] == reg32)) { + memcpy(value, &wland_user_data.phy.reg_val[idx][1], sizeof(u32)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: + if (wland_user_data.phy_channels.valid != 1) { + return -4; + } + + reg32 = *((u32 *)reg); + if (wland_user_data.phy_channels.flag != 0) { + for (idx = 0; idx < 8; idx++) { + if ((wland_user_data.phy_channels.flag & BIT(idx)) && + (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { + memcpy(value, &wland_user_data.phy_channels.reg_val[idx][1], 14 * sizeof(u32)); + break; + } else { + continue; + } + } + } + + if (8 == idx) { + return -4; + } + break; + default: + WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); + return -3; + } + + return 0; +} + +int rda5981_flash_get_mid(u8 *mid) +{ + *mid = 0xC8; + + return 0; +} + +int rda5981_flash_get_did(u8 *did) +{ + *did = 0x13; + + return 0; +} + +int rda5981_flash_get_jdid(u16 *jdid) +{ + *jdid = 0x4014; + + return 0; +} + +int rda5981_read_default_config(char *buf, u32 len, u32 flag) +{ + int ret = 0; + u32 addr; + u32 addr_offset = 0; + char *temp_buf = NULL, *temp_buf_aligned; + + switch (flag) { + case RDA5981_VBAT_CAL: + addr = 0x18000088; + break; + case RDA5981_GPADC0_CAL: + case RDA5981_GPADC1_CAL: + addr = 0x1800008C; + break; + case RDA5981_PRODUCT_ID: + addr = 0x18000084; + break; + case RDA5981_POWER_CLASS: + addr = 0x18000085; + break; + default: + WLAND_DBG(ERROR, "Unknown flag\n"); + return -1; + } + + addr_offset = addr % 4; + addr = (addr - addr_offset) & (flash_size -1); + + if (((u32)buf % 4) || (addr_offset != 0)) { + temp_buf = (char *)malloc(addr_offset + len + 4); + if (temp_buf == NULL) { + ret = -1; + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4 - (u32)temp_buf % 4); + } else { + temp_buf_aligned = temp_buf; + } + } else { + temp_buf_aligned = buf; + } + + core_util_critical_section_enter(); + spi_flash_flush_cache(); + SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, (len + addr_offset)); + core_util_critical_section_exit(); + + if (temp_buf_aligned != buf) { + memcpy(buf, temp_buf_aligned + addr_offset, len); + } +out: + if (temp_buf) { + free(temp_buf); + } + return ret; +} + +int rda5981_flash_read_vbat_cal(float *k, float *b) +{ + int ret = 0; + u32 value = 0; + u32 x1 = 0;//y1 3.0f + u32 x2 = 0;//y2 4.2f + float k_tmp = 0; + float b_tmp = 0; + + ret = rda5981_read_default_config((char *)&value, 4, RDA5981_VBAT_CAL); + + if (ret < 0) { + WLAND_DBG(ERROR, "read vbat_cal form flash fail\n"); + return -1; + } + if ((0 == (value & 0xFFFFFUL)) || (0xFFFFFUL == (value & 0xFFFFFUL))) { + WLAND_DBG(ERROR, "invalid vbat_cal:0x%08x\n", value); + return -1; + } else { + x1 = value & 0x3FFUL; + x2 = (value >> 10) & 0x3FFUL; + } + + if (x1 == x2) { + return -1; + } + + k_tmp = (4.2f - 3.0f) / (float)(x2 - x1); + b_tmp = 4.2f - k_tmp * x2; + + *k = k_tmp; + *b = b_tmp; + + return ret; +} diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c new file mode 100644 index 0000000..6ff0181 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c @@ -0,0 +1,366 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed_interface.h" +#include "wland_flash.h" + +//#define FLASH_PROTECT_ENABLE + +#define FLASH_CTL_REG_BASE 0x17fff000 +#define FLASH_CTL_TX_CMD_ADDR_REG (FLASH_CTL_REG_BASE + 0x00) +#define FLASH_CTL_TX_BLOCK_SIZE_REG (FLASH_CTL_REG_BASE + 0x04) +#define FLAHS_CTL_TX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x08) +#define FLASH_CTL_STATUS_REG (FLASH_CTL_REG_BASE + 0x0c) +#define FLAHS_CTL_RX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x10) + +#define WRITE_REG32(REG, VAL) ((*(volatile unsigned int*)(REG)) = (unsigned int)(VAL)) +#define WRITE_REG8(REG, VAL) ((*(volatile unsigned char*)(REG)) = (unsigned char)(VAL)) +#define MREAD_WORD(addr) *((volatile unsigned int *)(addr)) + +#define MID_GD 0xC8 +#define MID_WINBOND 0xEF + +#define FLASH_1M 0x100000 +#define FLASH_2M 0x200000 +#define FLASH_4M 0x400000 +extern unsigned int flash_size; + +#ifdef FLASH_PROTECT_ENABLE + +#define FLASH_WP_MASK 0x407c +#define FLASH_WP_NONE 0x0000 +#define FLASH_WP_ALL 0x1c + +#define FLASH_4M_WP_4K 0x0064 +#define FLASH_4M_WP_8K 0x0068 +#define FLASH_4M_WP_16K 0x006c +#define FLASH_4M_WP_32K 0x0070 +#define FLASH_4M_WP_1_64 0x0024 +#define FLASH_4M_WP_1_32 0x0028 +#define FLASH_4M_WP_1_16 0x002c +#define FLASH_4M_WP_1_8 0x0030 +#define FLASH_4M_WP_1_4 0x0034 +#define FLASH_4M_WP_1_2 0x0038 +#define FLASH_4M_WP_3_4 0x4014 +#define FLASH_4M_WP_7_8 0x4010 +#define FLASH_4M_WP_15_16 0x400c +#define FLASH_4M_WP_31_32 0x4008 +#define FLASH_4M_WP_63_64 0x4004 +#define FLASH_4M_WP_127_128 0x4058 +#define FLASH_4M_WP_255_256 0x404C +#define FLASH_4M_WP_1023_1024 0x4044 + +#define FLASH_2M_WP_4K 0x0064 +#define FLASH_2M_WP_8K 0x0068 +#define FLASH_2M_WP_16K 0x006c +#define FLASH_2M_WP_32K 0x0070 +#define FLASH_2M_WP_1_32 0x0024 +#define FLASH_2M_WP_1_16 0x0028 +#define FLASH_2M_WP_1_8 0x002c +#define FLASH_2M_WP_1_4 0x0050 +#define FLASH_2M_WP_1_2 0x0051 +#define FLASH_2M_WP_3_4 0x4010 +#define FLASH_2M_WP_7_8 0x400c +#define FLASH_2M_WP_15_16 0x4004 +#define FLASH_2M_WP_31_32 0x4000 +#define FLASH_2M_WP_63_64 0x4050 +#define FLASH_2M_WP_127_128 0x404c +#define FLASH_2M_WP_255_256 0x4048 +#define FLASH_2M_WP_511_512 0x4044 + + +#define FLASH_1M_WP_4K 0x0064 +#define FLASH_1M_WP_8K 0x0068 +#define FLASH_1M_WP_16K 0x006c +#define FLASH_1M_WP_32K 0x0070 +#define FLASH_1M_WP_1_16 0x0024 +#define FLASH_1M_WP_1_8 0x0028 +#define FLASH_1M_WP_1_4 0x002c +#define FLASH_1M_WP_1_2 0x0050 +#define FLASH_1M_WP_3_4 0x400C +#define FLASH_1M_WP_7_8 0x4008 +#define FLASH_1M_WP_15_16 0x4004 +#define FLASH_1M_WP_31_32 0x4050 +#define FLASH_1M_WP_63_64 0x404C +#define FLASH_1M_WP_127_128 0x4048 +#define FLASH_1M_WP_255_256 0x4044 + +static unsigned short flash_wrtie_protect_4M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + if (offset >= flash_size - flash_size/1024) { + wp = FLASH_4M_WP_1023_1024; + } else if(offset >= flash_size - flash_size/256) { + wp = FLASH_4M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_4M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_4M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_4M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_4M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_4M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_4M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_4M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_4M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_4M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_4M_WP_1_16; + } else if(offset >= flash_size/32) { + wp = FLASH_4M_WP_1_32; + } else if(offset >= flash_size/64) { + wp = FLASH_4M_WP_1_64; + } else if(offset >= 32 * 1024) { + wp = FLASH_4M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_4M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_4M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_4M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +static unsigned short flash_wrtie_protect_2M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + if (offset >= flash_size - flash_size/256) { + wp = FLASH_2M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_2M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_2M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_2M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_2M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_2M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_2M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_2M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_2M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_2M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_2M_WP_1_16; + } else if(offset >= flash_size/32) { + wp = FLASH_2M_WP_1_32; + } else if(offset >= 32 * 1024) { + wp = FLASH_2M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_2M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_2M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_2M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +static unsigned short flash_wrtie_protect_1M(unsigned short status, unsigned int offset) +{ + unsigned int wp = FLASH_WP_NONE; + + if (offset >= flash_size - flash_size/256) { + wp = FLASH_1M_WP_255_256; + } else if(offset >= flash_size - flash_size/128) { + wp = FLASH_1M_WP_127_128; + } else if(offset >= flash_size - flash_size/64) { + wp = FLASH_1M_WP_63_64; + } else if(offset >= flash_size - flash_size/32) { + wp = FLASH_1M_WP_31_32; + } else if(offset >= flash_size - flash_size/16) { + wp = FLASH_1M_WP_15_16; + } else if(offset >= flash_size - flash_size/8) { + wp = FLASH_1M_WP_7_8; + } else if(offset >= flash_size - flash_size/4) { + wp = FLASH_1M_WP_3_4; + } else if(offset >= flash_size/2) { + wp = FLASH_1M_WP_1_2; + } else if(offset >= flash_size/4) { + wp = FLASH_1M_WP_1_4; + } else if(offset >= flash_size/8) { + wp = FLASH_1M_WP_1_8; + } else if(offset >= flash_size/16) { + wp = FLASH_1M_WP_1_16; + } else if(offset >= 32 * 1024) { + wp = FLASH_1M_WP_32K; + } else if(offset >= 16 * 1024) { + wp = FLASH_1M_WP_16K; + } else if(offset >= 8 * 1024) { + wp = FLASH_1M_WP_8K; + } else if(offset >= 4 * 1024) { + wp = FLASH_1M_WP_4K; + } + + return (status & ~FLASH_WP_MASK) | wp; + +} + +void flash_wrtie_protect_all() +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + status = (status & ~FLASH_WP_MASK) | FLASH_WP_ALL; + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} + +void flash_wrtie_protect_none() +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + status = status & ~FLASH_WP_MASK; + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} + +void flash_wrtie_protect(unsigned int offset) +{ + unsigned short status; + unsigned char r1, r2; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); + wait_busy_down(); + r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); + wait_busy_down(); + r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + //mbed_error_printf("status %x %x\r\n", r2, r1); + + status = (r2 << 8) | r1; + if (flash_size == FLASH_4M) { + status = flash_wrtie_protect_4M(status, offset); + } else if(flash_size == FLASH_2M) { + status = flash_wrtie_protect_2M(status, offset); + } else if(flash_size == FLASH_1M) { + status = flash_wrtie_protect_1M(status, offset); + } else [ + LWIP_DEBUGF(NETIF_DEBUG,"flash_size is error\r\n"); + } + //mbed_error_printf("status %04x\r\n", status); + + spi_write_reset(); + wait_busy_down(); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); + WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); + wait_busy_down(); + spi_wip_reset(); + core_util_critical_section_exit(); + return; +} +#else +void flash_wrtie_protect_all() +{ + return; +} + +void flash_wrtie_protect_none() +{ + return; +} + +void flash_wrtie_protect(unsigned int offset) +{ + return; +} + +#endif +void rda5981_flash_init() +{ + unsigned int status3, status4, status5; + core_util_critical_section_enter(); + WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); + status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + + wait_busy_down(); + spi_wip_reset(); + WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x9F); + wait_busy_down(); + //WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); + //wait_busy_down(); + status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); + core_util_critical_section_exit(); + + if ((status5&0xff != 0x14) && (status5&0xff != 0x15) && (status5&0xff != 0x16)) { + mbed_error_printf("flash size error\r\n"); + return; + } + flash_size = (1 << (status5&0xff)); + flash_wrtie_protect_all(); + + return; +} diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c new file mode 100644 index 0000000..05a85ab --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wland_ota.h" +#include "wland_flash.h" +#include "rda5981_ota.h" +#include "wland_dbg.h" +#include "wland_types.h" +#include "critical.h" +#include +#include + +#define IMAGE_MAGIC 0xAEAE + +u32 wland_ota_partition_addr = 0; +u32 wland_ota_partition_len = 0; +u32 wland_crc_result = ~0UL; + +static u32 crc32(const u8 *p, u32 len, u32 crc) +{ + const u32 *crc32_tab = (const u32 *)CRC32_TABLE_ADDR; + + if (rda_ccfg_hwver() >= 4) { + crc32_tab = (const u32 *)CRC32_TABLE_ADDR_4; + } + /* Calculate CRC */ + while(len--) { + crc = crc32_tab[((crc & 0xFF) ^ *p++)] ^ (crc >> 8); + } + + return crc; +} + +static int rda5981_ota_erase_flash(u32 addr, u32 len) +{ + addr &= (flash_size -1); + rda5981_spi_erase_partition((void *)addr, len); + return 0; +} +//write without erase +static int rda5981_ota_write_flash(u32 addr, char *buf, u32 len) +{ + int ret = 0; + u8 *temp_buf = NULL, *temp_buf_aligned; + + addr &= (flash_size -1); + if ((u32)buf % 4) { + temp_buf = malloc(len + 3); + if (temp_buf == NULL) { + goto out; + } + if ((u32)temp_buf % 4) { + temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); + } else { + temp_buf_aligned = temp_buf; + } + memcpy(temp_buf_aligned, (unsigned char *)buf, len); + } else { + temp_buf_aligned = (u8 *)buf; + } + core_util_critical_section_enter(); + RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); + core_util_critical_section_exit(); + +out: + if (temp_buf) { + free(temp_buf); + } + return ret; +} + +int rda5981_write_partition_start(u32 addr, u32 img_len) +{ + if (addr < 0x18001000 || addr+img_len>0x18000000+flash_size) { + WLAND_DBG(ERROR,"write partition start addr error. (0x%08x, %u)\r\n", addr, img_len); + return -1; + } + if (addr%0x1000 || img_len%0x1000) { + WLAND_DBG(ERROR,"write partition start length error.(mast be 4k alignment) (0x%08x, %u)\r\n", addr, img_len); + return -1; + } + + WLAND_DBG(INFO, "rda5981_write_partition_start:0x%08x, %u\r\n", addr, img_len); + wland_ota_partition_addr = addr; + wland_ota_partition_len = img_len; + wland_crc_result = ~0U; + + rda5981_ota_erase_flash(addr, img_len); + return 0; +} +int rda5981_write_partition(u32 offset, const u8 *buf, u32 len) +{ + if (wland_ota_partition_addr==0 || offset+len>wland_ota_partition_len) { + WLAND_DBG(ERROR,"write partition error. out of start addr(0x%08x, %u). (0x%08x, %u)\r\n", + wland_ota_partition_addr, wland_ota_partition_len, offset, len); + return -1; + } + if (len%0x400) { + WLAND_DBG(ERROR,"write partition length error.(mast be 1k alignment) (0x%08x, %u)\r\n", offset, len); + return -1; + } + WLAND_DBG(DEBUG, "rda5981_write_partition:0x%08x, %u.(%02x)\r\n", + wland_ota_partition_addr + offset, len, buf[0]); + wland_crc_result = crc32(buf, len, wland_crc_result); + + WLAND_DBG(DEBUG, "rda5981_write_partition: wland_crc_result 0x%08x\r\n", + wland_crc_result); + return rda5981_ota_write_flash(wland_ota_partition_addr + offset, (char *)buf, len); + //return rda5981_write_flash(wland_ota_partition_addr + offset, buf, len); +} +int rda5981_write_partition_end(void) +{ + WLAND_DBG(INFO, "check crc32:0x%08x, %u\r\n", wland_ota_partition_addr, wland_ota_partition_len); + if (wland_ota_partition_addr == 0) { + WLAND_DBG(ERROR,"OTA is not started\r\n"); + return -1; + } + core_util_critical_section_enter(); + spi_flash_flush_cache(); + //u32 crc32_check = crc32(wland_ota_partition_addr, wland_ota_partition_len, ~0U); + u32 crc32_check = bootrom_crc32((unsigned char *)wland_ota_partition_addr, wland_ota_partition_len); + core_util_critical_section_exit(); + WLAND_DBG(INFO, "rda5981_write_partition_end:0x%08x:0x%08x\r\n", wland_crc_result, crc32_check); + wland_ota_partition_addr = 0UL; + + if (crc32_check == wland_crc_result) { + return 0; + } else { + WLAND_DBG(ERROR,"check crc32 error\r\n"); + return -1; + } +} diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.cpp b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.cpp new file mode 100644 index 0000000..9ab3557 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.cpp @@ -0,0 +1,291 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "cmsis_os.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "mbed_shared_queues.h" +#include "netsocket/nsapi_types.h" +#include "lwip/arch.h" +#include "lwip/pbuf.h" +#include "rda5991h_wland.h" +#include "rda5981x_emac_config.h" +#include "rda5981x_emac.h" +#include "rda_sys_wrapper.h" +#include "maclib_task.h" + +#define RDA_HWADDR_SIZE (6) +#define RDA_ETH_MTU_SIZE 1500 +#define RDA_ETH_IF_NAME "st" + +#define RX_PRIORITY (osPriorityNormal) +#define TX_PRIORITY (osPriorityNormal) +#define PHY_PRIORITY (osPriorityNormal) + +extern void *packet_rx_queue; + +RDA5981x_EMAC::RDA5981x_EMAC() +{ +} + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the memory buffer chain that is passed to the function. + * + * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return true if the packet could be sent + * false value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +bool RDA5981x_EMAC::link_out(emac_mem_buf_t *buf) +{ + emac_mem_buf_t *q, *p = buf; + + u32_t actual_txlen = 0; + u8_t **data = NULL; + u16_t retry = 400; + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); + + while ((data == NULL) && (retry-- > 0)) { + data = (u8_t**)wland_get_databuf(); + osThreadYield(); + } + if (data == NULL) { + LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); + memory_manager->free(buf); + return false; + } + + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + /* Send the data from the pbuf to the interface, one pbuf at a + time. The size of the data in each pbuf is kept in the ->len + variable. */ + memcpy(&((*data)[actual_txlen+2]), memory_manager->get_ptr(q), memory_manager->get_len(q));//reserve wid header length + actual_txlen += memory_manager->get_len(q); + if (actual_txlen > 1514 || actual_txlen > memory_manager->get_total_len(p)) { + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", actual_txlen, memory_manager->get_total_len(p))); + memory_manager->free(buf); + return false; + } + } + + /* Signal rda5996 that packet should be sent */ + if (actual_txlen == memory_manager->get_total_len(p)) { + wland_txip_data((void*)data, actual_txlen, 0); + memory_manager->free(buf); + return true; + } + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", + actual_txlen, memory_manager->get_total_len(p))); + + memory_manager->free(buf); + return false; +} + +/** + * Should allocate a contiguous memory buffer and transfer the bytes of the incoming + * packet to the buffer. + * + * @param buf If a frame was received and the memory buffer allocation was successful, a memory + * buffer filled with the received packet (including MAC header) + * @return negative value when no more frames, + * zero when frame is received + */ +emac_mem_buf_t * RDA5981x_EMAC::low_level_input(u8_t *data, int len) +{ + emac_mem_buf_t *p, *q; + u16_t index = 0; + + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input enter, rxlen:%d\n", len)); + + /* Obtain the size of the packet and put it into the "len" + variable. */ + if (!len) { + return NULL; + } + + /* We allocate a pbuf chain of pbufs from the pool. */ + p = memory_manager->alloc_pool(len, 0); + if (p != NULL) { + /* We iterate over the pbuf chain until we have read the entire + * packet into the pbuf. */ + for (q = p; q != NULL; q = memory_manager->get_next(q)) { + /* Read enough bytes to fill this pbuf in the chain. The + * available data in the pbuf is given by the q->len + * variable. + * This does not necessarily have to be a memcpy, you can also preallocate + * pbufs for a DMA-enabled MAC and after receiving truncate it to the + * actually received size. In this case, ensure the tot_len member of the + * pbuf is the sum of the chained pbuf len members. + */ + /* load rx data from 96 to local mem_pool */ + memcpy(memory_manager->get_ptr(q), &data[index], memory_manager->get_len(q)); + index += memory_manager->get_len(q); + + if (index >= len) { + break; + } + } + + } else { + /* Drop this packet */ + LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); + + return NULL; + } + return p; +} + + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +void RDA5981x_EMAC::packet_rx() +{ + rda_msg msg; + packet_rx_queue = rda_mail_create(10, sizeof(unsigned int)*4); + /* move received packet into a new buf */ + while (1) { + emac_mem_buf_t *p = NULL; + rda_mail_get(packet_rx_queue, (void*)&msg, osWaitForever); + switch(msg.type) { + case 0: + p = low_level_input((unsigned char*)msg.arg1, msg.arg2); + if (p == NULL) { + break; + } + if (p) { + emac_link_input_cb(p); + } + break; + case 1: + emac_link_state_cb(msg.arg1); + break; + default: + break; + } + } +} + +void RDA5981x_EMAC::thread_function(void *pvParameters) +{ + static struct RDA5981x_EMAC *rda5981x_enet = static_cast(pvParameters); + rda5981x_enet->packet_rx(); +} + +bool RDA5981x_EMAC::power_up() +{ + /* Initialize the hardware */ + static int init_flag = 0; + if (init_flag == 0) { + wland_reg_func(); + rda_thread_new("maclib_thread", maclib_task, NULL, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); + rda_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + rda_thread_new("packet_rx", RDA5981x_EMAC::thread_function, this, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(100); + wland_sta_init(); + init_flag = 1; + } + + return true; +} + +uint32_t RDA5981x_EMAC::get_mtu_size() const +{ + return RDA_ETH_MTU_SIZE; +} + +uint32_t RDA5981x_EMAC::get_align_preference() const +{ + return 0; +} + +void RDA5981x_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, RDA_ETH_IF_NAME, (size < sizeof(RDA_ETH_IF_NAME)) ? size : sizeof(RDA_ETH_IF_NAME)); +} + +uint8_t RDA5981x_EMAC::get_hwaddr_size() const +{ + return RDA_HWADDR_SIZE; +} + +bool RDA5981x_EMAC::get_hwaddr(uint8_t *addr) const +{ + mbed_mac_address((char *)addr); + return true; +} + +void RDA5981x_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void RDA5981x_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void RDA5981x_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::power_down() +{ + /* No-op at this stage */ +} + +void RDA5981x_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +RDA5981x_EMAC &RDA5981x_EMAC::get_instance() +{ + static RDA5981x_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return RDA5981x_EMAC::get_instance(); +} + diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.h new file mode 100644 index 0000000..fa95ba4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac.h @@ -0,0 +1,160 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32_EMAC_H_ +#define STM32_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Mutex.h" + +class RDA5981x_EMAC : public EMAC { +public: + RDA5981x_EMAC(); + + static RDA5981x_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + void packet_rx(); + emac_mem_buf_t * low_level_input(u8_t *data, int len); + static void thread_function(void *pvParameters); + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + +}; + +#endif /* K64F_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac_config.h b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac_config.h new file mode 100644 index 0000000..717d423 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RDA_EMAC/rda5981x_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2019 Unisoc Communications Inc. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define THREAD_STACKSIZE 512 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.cpp b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.cpp new file mode 100644 index 0000000..6484f53 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.cpp @@ -0,0 +1,223 @@ +/* Copyright (c) 2018 Renesas Electronics Corporation. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "cmsis_os.h" +#include "rtos/ThisThread.h" +#include "netsocket/nsapi_types.h" +#include "mbed_shared_queues.h" +#include "rza1_eth.h" +#include "rza1_eth_ext.h" +#include "rza1_emac.h" + +#define RZ_A1_ETH_IF_NAME "en" + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() { + return RZ_A1_EMAC::get_instance(); +} + +RZ_A1_EMAC &RZ_A1_EMAC::get_instance() { + static RZ_A1_EMAC emac; + return emac; +} + +RZ_A1_EMAC::RZ_A1_EMAC() : hwaddr(), hwaddr_set(false), power_on(false), connect_sts(false), + link_mode_last(NEGO_FAIL), recvThread(osPriorityNormal, 896) +{ +} + +uint32_t RZ_A1_EMAC::get_mtu_size() const +{ + return 1500; +} + +uint32_t RZ_A1_EMAC::get_align_preference() const +{ + return 0; +} + +void RZ_A1_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, RZ_A1_ETH_IF_NAME, (size < sizeof(RZ_A1_ETH_IF_NAME)) ? size : sizeof(RZ_A1_ETH_IF_NAME)); +} + +uint8_t RZ_A1_EMAC::get_hwaddr_size() const +{ + return 6; +} + +bool RZ_A1_EMAC::get_hwaddr(uint8_t *addr) const +{ + return false; +} + +void RZ_A1_EMAC::set_hwaddr(const uint8_t *addr) +{ + memcpy(hwaddr, addr, sizeof(hwaddr)); + hwaddr_set = true; + + /* Reconnect */ + if (power_on != false) { + rza1_ethernet_cfg_t ethcfg; + ethcfg.int_priority = 6; + ethcfg.recv_cb = &_recv_callback; + ethcfg.ether_mac = NULL; + ethcfg.ether_mac = (char *)hwaddr; + ethernetext_init(ðcfg); + } +} + +bool RZ_A1_EMAC::link_out(emac_mem_buf_t *buf) +{ + emac_mem_buf_t *copy_buf = buf; + uint32_t retry_cnt; + bool result = false; + int write_size; + int total_write_size = 0; + + while ((copy_buf != NULL) && (memory_manager->get_ptr(copy_buf) != NULL) && (memory_manager->get_len(copy_buf) != 0)) { + for (retry_cnt = 0; retry_cnt < 100; retry_cnt++) { + write_size = rza1_ethernet_write((char *)memory_manager->get_ptr(copy_buf), memory_manager->get_len(copy_buf)); + if (write_size != 0) { + total_write_size += write_size; + break; + } + osDelay(1); + } + copy_buf = memory_manager->get_next(copy_buf); + } + memory_manager->free(buf); + + if (total_write_size > 0) { + if (rza1_ethernet_send() == 1) { + result = true; + } + } + + return result; +} + +bool RZ_A1_EMAC::power_up() +{ + if (power_on != false) { + return true; + } + + rza1_ethernet_cfg_t ethcfg; + ethcfg.int_priority = 6; + ethcfg.recv_cb = &_recv_callback; + ethcfg.ether_mac = NULL; + if (hwaddr_set) { + ethcfg.ether_mac = (char *)hwaddr; + } + ethernetext_init(ðcfg); + + /* task */ + recvThread.start(mbed::callback(this, &RZ_A1_EMAC::recv_task)); + phy_task_handle = mbed::mbed_event_queue()->call_every(200, mbed::callback(this, &RZ_A1_EMAC::phy_task)); + + power_on = true; + return true; +} + +void RZ_A1_EMAC::power_down() +{ + power_on = false; +} + +void RZ_A1_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void RZ_A1_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void RZ_A1_EMAC::add_multicast_group(const uint8_t *addr) +{ + ethernetext_add_multicast_group(addr); +} + +void RZ_A1_EMAC::remove_multicast_group(const uint8_t *addr) +{ + ethernetext_remove_multicast_group(addr); +} + +void RZ_A1_EMAC::set_all_multicast(bool all) +{ + ethernetext_set_all_multicast(all); +} + +void RZ_A1_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + + +void RZ_A1_EMAC::_recv_callback(void) { + get_instance().recv_callback(); +} + +void RZ_A1_EMAC::recv_callback(void) { + recvThread.flags_set(1); +} + +void RZ_A1_EMAC::recv_task(void) { + uint16_t recv_size; + emac_mem_buf_t *buf; + int cnt; + + while (1) { + rtos::ThisThread::flags_wait_all(1); + for (cnt = 0; cnt < 16; cnt++) { + recv_size = rza1_ethernet_receive(); + if (recv_size == 0) { + break; + } + buf = memory_manager->alloc_heap(recv_size, 0); + if (buf != NULL) { + (void)rza1_ethernet_read((char *)memory_manager->get_ptr(buf), memory_manager->get_len(buf)); + emac_link_input_cb(buf); + } + } + } +} + +void RZ_A1_EMAC::phy_task(void) +{ + if (rza1_ethernet_link() == 1) { + int link_mode = ethernetext_chk_link_mode(); + if (link_mode != link_mode_last) { + if (connect_sts != false) { + emac_link_state_cb(false); + } + if (link_mode != NEGO_FAIL) { + ethernetext_set_link_mode(link_mode); + emac_link_state_cb(true); + connect_sts = true; + } + link_mode_last = link_mode; + } + } else { + if (connect_sts != false) { + emac_link_state_cb(false); + link_mode_last = NEGO_FAIL; + connect_sts = false; + } + } +} + diff --git a/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.h b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.h new file mode 100644 index 0000000..70f5507 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_emac.h @@ -0,0 +1,169 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RZ_A1_EMAC_H +#define RZ_A1_EMAC_H + +#include "EMAC.h" +#include "rtos/Thread.h" + +class RZ_A1_EMAC : public EMAC { +public: + RZ_A1_EMAC(); + + static RZ_A1_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + +private: + EMACMemoryManager *memory_manager; /**< Memory manager */ + uint8_t hwaddr[6]; + bool hwaddr_set; + bool power_on; + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + bool connect_sts; + int link_mode_last; + rtos::Thread recvThread; + int phy_task_handle; /**< Handle for phy task event */ + + static void _recv_callback(void); + void recv_callback(void); + void recv_task(void); + void phy_task(void); + +}; + +#endif /* RZ_A1_EMAC_H */ diff --git a/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.c b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.c new file mode 100644 index 0000000..3777327 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.c @@ -0,0 +1,793 @@ +/* Copyright (c) 2020 Renesas Electronics Corporation. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "rza1_eth.h" +#include "cmsis.h" +#include "mbed_interface.h" +#include "mbed_toolchain.h" +#include "mbed_error.h" +#include "iodefine.h" +#include "rza1_eth_ext.h" + +#if DEVICE_ETHERNET + +/* Descriptor info */ +#define NUM_OF_TX_DESCRIPTOR (16) +#define NUM_OF_RX_DESCRIPTOR (16) +#define SIZE_OF_BUFFER (1600) /* Must be an integral multiple of 32 */ +#define MAX_SEND_SIZE (1514) +/* Ethernet Descriptor Value Define */ +#define TD0_TFP_TOP_BOTTOM (0x30000000) +#define TD0_TACT (0x80000000) +#define TD0_TDLE (0x40000000) +#define RD0_RACT (0x80000000) +#define RD0_RDLE (0x40000000) +#define RD0_RFE (0x08000000) +#define RD0_RCSE (0x04000000) +#define RD0_RFS (0x03FF0000) +#define RD0_RCS (0x0000FFFF) +#define RD0_RFS_RFOF (0x02000000) +#define RD0_RFS_RUAF (0x00400000) +#define RD0_RFS_RRF (0x00100000) +#define RD0_RFS_RTLF (0x00080000) +#define RD0_RFS_RTSF (0x00040000) +#define RD0_RFS_PRE (0x00020000) +#define RD0_RFS_CERF (0x00010000) +#define RD0_RFS_ERROR (RD0_RFS_RFOF | RD0_RFS_RUAF | RD0_RFS_RRF | RD0_RFS_RTLF | \ + RD0_RFS_RTSF | RD0_RFS_PRE | RD0_RFS_CERF) +#define RD1_RDL_MSK (0x0000FFFF) +/* PHY Register */ +#define BASIC_MODE_CONTROL_REG (0) +#define BASIC_MODE_STATUS_REG (1) +#define PHY_IDENTIFIER1_REG (2) +#define PHY_IDENTIFIER2_REG (3) +#define PHY_SP_CTL_STS_REG (31) +/* MII management interface access */ +#define PHY_ADDR (0) /* Confirm the pin connection of the PHY-LSI */ +#define PHY_ST (1) +#define PHY_WRITE (1) +#define PHY_READ (2) +#define MDC_WAIT (6) /* 400ns/4 */ +#define BASIC_STS_MSK_LINK (0x0004) /* Link Status */ +#define BASIC_STS_MSK_AUTO_CMP (0x0020) /* Auto-Negotiate Complete */ +#define M_PHY_ID (0xFFFFFFF0) +#define PHY_ID_LAN8710A (0x0007C0F0) +/* ETHERPIR0 */ +#define PIR0_MDI (0x00000008) +#define PIR0_MDO (0x00000004) +#define PIR0_MMD (0x00000002) +#define PIR0_MDC (0x00000001) +#define PIR0_MDC_HIGH (0x00000001) +#define PIR0_MDC_LOW (0x00000000) +/* ETHEREDRRR0 */ +#define EDRRR0_RR (0x00000001) +/* ETHEREDTRR0 */ +#define EDTRR0_TR (0x00000003) +/* software wait */ +#define LOOP_100us (6700) /* Loop counter for software wait 6666=100us/((1/400MHz)*6cyc) */ + +#define EDMAC_EESIPR_INI_RECV (0x0205001F) /* 0x02000000 : Detect reception suspended */ + /* 0x00040000 : Detect frame reception */ + /* 0x00010000 : Receive FIFO overflow */ + /* 0x00000010 : Residual bit frame reception */ + /* 0x00000008 : Long frame reception */ + /* 0x00000004 : Short frame reception */ + /* 0x00000002 : PHY-LSI reception error */ + /* 0x00000001 : Receive frame CRC error */ +#define EDMAC_EESIPR_INI_EtherC (0x00400000) /* 0x00400000 : E-MAC status register */ + +void rza1_ethernet_address(char *); +void rza1_ethernet_set_link(int, int); + + +/* Send descriptor */ +typedef struct tag_edmac_send_desc { + uint32_t td0; + uint32_t td1; + uint8_t *td2; + uint32_t padding4; +} edmac_send_desc_t; + +/* Receive descriptor */ +typedef struct tag_edmac_recv_desc { + uint32_t rd0; + uint32_t rd1; + uint8_t *rd2; + uint32_t padding4; +} edmac_recv_desc_t; + +/* memory */ +/* The whole transmit/receive descriptors (must be allocated in 16-byte boundaries) */ +/* Transmit/receive buffers (must be allocated in 16-byte boundaries) */ +#if defined(__ICCARM__) +#pragma data_alignment=16 +static uint8_t rza1_ethernet_nc_memory[(sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR) + + (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR) + + (NUM_OF_TX_DESCRIPTOR * SIZE_OF_BUFFER) + + (NUM_OF_RX_DESCRIPTOR * SIZE_OF_BUFFER)] //16 bytes aligned! + @ ".mirrorram"; +#else +static uint8_t rza1_ethernet_nc_memory[(sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR) + + (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR) + + (NUM_OF_TX_DESCRIPTOR * SIZE_OF_BUFFER) + + (NUM_OF_RX_DESCRIPTOR * SIZE_OF_BUFFER)] + __attribute((section("NC_BSS"),aligned(16))); //16 bytes aligned! +#endif +static int32_t rx_read_offset; /* read offset */ +static int32_t tx_wite_offset; /* write offset */ +static uint32_t send_top_index; +static uint32_t recv_top_index; +static int32_t Interrupt_priority; +static edmac_send_desc_t *p_eth_desc_dsend = NULL; +static edmac_recv_desc_t *p_eth_desc_drecv = NULL; +static edmac_recv_desc_t *p_recv_end_desc = NULL; +static ethernetext_cb_fnc *p_recv_cb_fnc = NULL; +static char mac_addr[6] = {0x00, 0x02, 0xF7, 0xF0, 0x00, 0x00}; /* MAC Address */ +static uint32_t phy_id = 0; +static uint32_t start_stop = 1; /* 0:stop 1:start */ +static uint32_t tsu_ten_tmp = 0; + +volatile struct st_ether_from_tsu_adrh0* ETHER_FROM_TSU_ADRH0_ARRAY[ ETHER_FROM_TSU_ADRH0_ARRAY_COUNT ] = + /* ->MISRA 11.3 */ /* ->SEC R2.7.1 */ + ETHER_FROM_TSU_ADRH0_ARRAY_ADDRESS_LIST; + /* <-MISRA 11.3 */ /* <-SEC R2.7.1 */ + +/* function */ +static void lan_reg_reset(void); +static void lan_desc_create(void); +static void lan_reg_set(int32_t link); +static uint16_t phy_reg_read(uint16_t reg_addr); +static void phy_reg_write(uint16_t reg_addr, uint16_t data); +static void mii_preamble(void); +static void mii_cmd(uint16_t reg_addr, uint32_t option); +static void mii_reg_read(uint16_t *data); +static void mii_reg_write(uint16_t data); +static void mii_z(void); +static void mii_write_1(void); +static void mii_write_0(void); +static void set_ether_pir(uint32_t set_data); +static void wait_100us(int32_t wait_cnt); + + +int ethernetext_init(rza1_ethernet_cfg_t *p_ethcfg) { + int32_t i; + uint16_t val; + + CPGSTBCR7 &= ~(CPG_STBCR7_BIT_MSTP74); /* enable ETHER clock */ + +#if defined(TARGET_RZ_A1H) + /* P4_2(PHY Reset) */ + GPIOP4 &= ~0x0004; /* Outputs low level */ + GPIOPMC4 &= ~0x0004; /* Port mode */ + GPIOPM4 &= ~0x0004; /* Output mode */ + + /* GPIO P1 P1_14(ET_COL) */ + GPIOPMC1 |= 0x4000; + GPIOPFCAE1 &= ~0x4000; + GPIOPFCE1 |= 0x4000; + GPIOPFC1 |= 0x4000; + + /* P3_0(ET_TXCLK), P3_3(ET_MDIO), P3_4(ET_RXCLK), P3_5(ET_RXER), P3_6(ET_RXDV) */ + GPIOPMC3 |= 0x0079; + GPIOPFCAE3 &= ~0x0079; + GPIOPFCE3 &= ~0x0079; + GPIOPFC3 |= 0x0079; + GPIOPIPC3 |= 0x0079; + + /* P5_9(ET_MDC) */ + GPIOPMC5 |= 0x0200; + GPIOPFCAE5 &= ~0x0200; + GPIOPFCE5 &= ~0x0200; + GPIOPFC5 |= 0x0200; + GPIOPIPC5 |= 0x0200; + + /* P10_1(ET_TXER), P10_2(ET_TXEN), P10_3(ET_CRS), P10_4(ET_TXD0), P10_5(ET_TXD1) */ + /* P10_6(ET_TXD2), P10_7(ET_TXD3), P10_8(ET_RXD0), P10_9(ET_RXD1), P10_10(ET_RXD2), P10_11(ET_RXD3) */ + GPIOPMC10 |= 0x0FFE; + GPIOPFCAE10 &= ~0x0FFE; + GPIOPFCE10 |= 0x0FFE; + GPIOPFC10 |= 0x0FFE; + GPIOPIPC10 |= 0x0FFE; + + /* Resets the E-MAC,E-DMAC */ + lan_reg_reset(); + + /* PHY Reset */ + GPIOP4 &= ~0x0004; /* P4_2 Outputs low level */ + wait_100us(250); /* 25msec */ + GPIOP4 |= 0x0004; /* P4_2 Outputs high level */ + wait_100us(100); /* 10msec */ +#else +#error "There is no initialization processing." +#endif + + /* Resets the PHY-LSI */ + phy_reg_write(BASIC_MODE_CONTROL_REG, 0x8000); + for (i = 10000; i > 0; i--) { + val = phy_reg_read(BASIC_MODE_CONTROL_REG); + if (((uint32_t)val & 0x8000uL) == 0) { + break; /* Reset complete */ + } + } + + phy_id = ((uint32_t)phy_reg_read(PHY_IDENTIFIER1_REG) << 16) + | (uint32_t)phy_reg_read(PHY_IDENTIFIER2_REG); + + Interrupt_priority = p_ethcfg->int_priority; + p_recv_cb_fnc = p_ethcfg->recv_cb; + start_stop = 1; + + if (p_ethcfg->ether_mac != NULL) { + (void)memcpy(mac_addr, p_ethcfg->ether_mac, sizeof(mac_addr)); + } else { + rza1_ethernet_address(mac_addr); /* Get MAC Address */ + } + + return 0; +} + +void ethernetext_start_stop(int32_t mode) { + if (mode == 1) { + /* start */ + ETHEREDTRR0 |= EDTRR0_TR; + ETHEREDRRR0 |= EDRRR0_RR; + start_stop = 1; + } else { + /* stop */ + ETHEREDTRR0 &= ~EDTRR0_TR; + ETHEREDRRR0 &= ~EDRRR0_RR; + start_stop = 0; + } +} + +int ethernetext_chk_link_mode(void) { + int32_t link; + uint16_t data; + + if ((phy_id & M_PHY_ID) == PHY_ID_LAN8710A) { + data = phy_reg_read(PHY_SP_CTL_STS_REG); + switch (((uint32_t)data >> 2) & 0x00000007) { + case 0x0001: + link = HALF_10M; + break; + case 0x0005: + link = FULL_10M; + break; + case 0x0002: + link = HALF_TX; + break; + case 0x0006: + link = FULL_TX; + break; + default: + link = NEGO_FAIL; + break; + } + } else { + link = NEGO_FAIL; + } + + return link; +} + +void ethernetext_set_link_mode(int32_t link) { + lan_reg_reset(); /* Resets the E-MAC,E-DMAC */ + lan_desc_create(); /* Initialize of buffer memory */ + lan_reg_set(link); /* E-DMAC, E-MAC initialization */ +} + +void ethernetext_add_multicast_group(const uint8_t *addr) { + uint32_t cnt; + uint32_t tmp_data_h; + uint32_t tmp_data_l; + + if (tsu_ten_tmp == 0xFFFFFFFF) { + ethernetext_set_all_multicast(1); + } else { + tmp_data_h = ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]); + tmp_data_l = ((uint32_t)addr[4] << 8) | ((uint32_t)addr[5]); + + for (cnt = 0; cnt < 32; cnt++) { + if ((tsu_ten_tmp & (0x80000000 >> cnt)) == 0) { + while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { + ; + } + ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 = tmp_data_h; + while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { + ; + } + ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 = tmp_data_l; + if ((ETHERECMR0 & 0x00002000) != 0) { + ETHERTSU_TEN |= (0x80000000 >> cnt); + } + tsu_ten_tmp |= (0x80000000 >> cnt); + break; + } + } + } +} + +void ethernetext_remove_multicast_group(const uint8_t *addr) { + uint32_t cnt; + uint32_t tmp_data_h; + uint32_t tmp_data_l; + + tmp_data_h = ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]); + tmp_data_l = ((uint32_t)addr[4] << 8) | ((uint32_t)addr[5]); + + for (cnt = 0; cnt< 32; cnt++) { + if ((ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 == tmp_data_h) && + (ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 == tmp_data_l)) { + while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { + ; + } + ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 = 0; + while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { + ; + } + ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 = 0; + + ETHERTSU_TEN &= ~(0x80000000 >> cnt); + tsu_ten_tmp &= ~(0x80000000 >> cnt); + break; + } + } +} + +void ethernetext_set_all_multicast(int all) { + if (all != 0) { + ETHERECMR0 &= ~(0x00002000); + ETHERTSU_TEN = 0x00000000; + } else { + ETHERECMR0 |= 0x00002000; + ETHERTSU_TEN = tsu_ten_tmp; + } +} + + +int rza1_ethernet_init() { + rza1_ethernet_cfg_t ethcfg; + + ethcfg.int_priority = 5; + ethcfg.recv_cb = NULL; + ethcfg.ether_mac = NULL; + ethernetext_init(ðcfg); + rza1_ethernet_set_link(-1, 0); /* Auto-Negotiation */ + + return 0; +} + +void rza1_ethernet_free() { + ETHERARSTR |= 0x00000001; /* ETHER software reset */ + CPGSTBCR7 |= CPG_STBCR7_BIT_MSTP74; /* disable ETHER clock */ +} + +int rza1_ethernet_write(const char *data, int slen) { + edmac_send_desc_t *p_send_desc; + int32_t copy_size; + + if ((p_eth_desc_dsend == NULL) || (data == NULL) || (slen < 0) + || (tx_wite_offset < 0) || (tx_wite_offset >= MAX_SEND_SIZE)) { + copy_size = 0; + } else { + p_send_desc = &p_eth_desc_dsend[send_top_index]; /* Current descriptor */ + if ((p_send_desc->td0 & TD0_TACT) != 0) { + copy_size = 0; + } else { + copy_size = MAX_SEND_SIZE - tx_wite_offset; + if (copy_size > slen) { + copy_size = slen; + } + (void)memcpy(&p_send_desc->td2[tx_wite_offset], data, copy_size); + tx_wite_offset += copy_size; + } + } + + return copy_size; +} + +int rza1_ethernet_send() { + edmac_send_desc_t *p_send_desc; + int32_t ret; + + if ((p_eth_desc_dsend == NULL) || (tx_wite_offset <= 0)) { + ret = 0; + } else { + /* Transfer 1 frame */ + p_send_desc = &p_eth_desc_dsend[send_top_index]; /* Current descriptor */ + + /* Sets the frame length */ + p_send_desc->td1 = ((uint32_t)tx_wite_offset << 16); + tx_wite_offset = 0; + + /* Sets the transmit descriptor to transmit again */ + p_send_desc->td0 &= (TD0_TACT | TD0_TDLE | TD0_TFP_TOP_BOTTOM); + p_send_desc->td0 |= TD0_TACT; + if ((start_stop == 1) && ((ETHEREDTRR0 & EDTRR0_TR) != EDTRR0_TR)) { + ETHEREDTRR0 |= EDTRR0_TR; + } + + /* Update the current descriptor */ + send_top_index++; + if (send_top_index >= NUM_OF_TX_DESCRIPTOR) { + send_top_index = 0; + } + ret = 1; + } + + return ret; +} + +int rza1_ethernet_receive() { + edmac_recv_desc_t *p_recv_desc; + int32_t receive_size = 0; + + if (p_eth_desc_drecv != NULL) { + if (p_recv_end_desc != NULL) { + /* Sets the receive descriptor to receive again */ + p_recv_end_desc->rd0 &= (RD0_RACT | RD0_RDLE); + p_recv_end_desc->rd0 |= RD0_RACT; + if ((start_stop == 1) && ((ETHEREDRRR0 & EDRRR0_RR) == 0)) { + ETHEREDRRR0 |= EDRRR0_RR; + } + p_recv_end_desc = NULL; + } + + p_recv_desc = &p_eth_desc_drecv[recv_top_index]; /* Current descriptor */ + if ((p_recv_desc->rd0 & RD0_RACT) == 0) { + /* Receives 1 frame */ + if (((p_recv_desc->rd0 & RD0_RFE) != 0) && ((p_recv_desc->rd0 & RD0_RFS_ERROR) != 0)) { + /* Receive frame error */ + /* Sets the receive descriptor to receive again */ + p_recv_desc->rd0 &= (RD0_RACT | RD0_RDLE); + p_recv_desc->rd0 |= RD0_RACT; + if ((start_stop == 1) && ((ETHEREDRRR0 & EDRRR0_RR) == 0)) { + ETHEREDRRR0 |= EDRRR0_RR; + } + } else { + /* Copies the received frame */ + rx_read_offset = 0; + p_recv_end_desc = p_recv_desc; + receive_size = (p_recv_desc->rd1 & RD1_RDL_MSK); /* number of bytes received */ + } + + /* Update the current descriptor */ + recv_top_index++; + if (recv_top_index >= NUM_OF_TX_DESCRIPTOR) { + recv_top_index = 0; + } + } + } + + return receive_size; +} + +int rza1_ethernet_read(char *data, int dlen) { + edmac_recv_desc_t *p_recv_desc = p_recv_end_desc; /* Read top descriptor */ + int32_t copy_size; + + if ((data == NULL) || (dlen < 0) || (p_recv_desc == NULL)) { + copy_size = 0; + } else { + copy_size = (p_recv_desc->rd1 & RD1_RDL_MSK) - rx_read_offset; + if (copy_size > dlen) { + copy_size = dlen; + } + (void)memcpy(data, &p_recv_desc->rd2[rx_read_offset], (size_t)copy_size); + rx_read_offset += copy_size; + } + + return copy_size; +} + +void rza1_ethernet_address(char *mac) { + if (mac != NULL) { + mbed_mac_address(mac); /* Get MAC Address */ + } +} + +int rza1_ethernet_link(void) { + int32_t ret; + uint16_t data; + + data = phy_reg_read(BASIC_MODE_STATUS_REG); + if (((uint32_t)data & BASIC_STS_MSK_LINK) != 0) { + ret = 1; + } else { + ret = 0; + } + + return ret; +} + +void rza1_ethernet_set_link(int speed, int duplex) { + uint16_t data; + int32_t i; + int32_t link; + + if ((speed < 0) || (speed > 1)) { + data = 0x1000; /* Auto-Negotiation Enable */ + phy_reg_write(BASIC_MODE_CONTROL_REG, data); + for (i = 0; i < 1000; i++) { + data = phy_reg_read(BASIC_MODE_STATUS_REG); + if (((uint32_t)data & BASIC_STS_MSK_AUTO_CMP) != 0) { + break; + } + wait_100us(10); + } + } else { + data = (uint16_t)(((uint32_t)speed << 13) | ((uint32_t)duplex << 8)); + phy_reg_write(BASIC_MODE_CONTROL_REG, data); + wait_100us(1); + } + + link = ethernetext_chk_link_mode(); + ethernetext_set_link_mode(link); +} + +void INT_Ether(void) { + uint32_t stat_edmac; + uint32_t stat_etherc; + + /* Clear the interrupt request flag */ + stat_edmac = (ETHEREESR0 & ETHEREESIPR0); /* Targets are restricted to allowed interrupts */ + ETHEREESR0 = stat_edmac; + /* Reception-related */ + if (stat_edmac & EDMAC_EESIPR_INI_RECV) { + if (p_recv_cb_fnc != NULL) { + p_recv_cb_fnc(); + } + } + /* E-MAC-related */ + if (stat_edmac & EDMAC_EESIPR_INI_EtherC) { + /* Clear the interrupt request flag */ + stat_etherc = (ETHERECSR0 & ETHERECSIPR0); /* Targets are restricted to allowed interrupts */ + ETHERECSR0 = stat_etherc; + } +} + +static void lan_reg_reset(void) { + volatile int32_t j = 400; /* Wait for B dia 256 cycles ((I dia/B dia)*256)/6cyc = 8*256/6 = 342 */ + + ETHERARSTR |= 0x00000001; /* ETHER software reset */ + while (j--) { + /* Do Nothing */ + } + + ETHEREDSR0 |= 0x00000003; /* E-DMAC software reset */ + ETHEREDMR0 |= 0x00000003; /* Set SWRR and SWRT simultaneously */ + + /* Check clear software reset */ + while ((ETHEREDMR0 & 0x00000003) != 0) { + /* Do Nothing */ + } +} + +static void lan_desc_create(void) { + int32_t i; + uint8_t *p_memory_top; + + (void)memset((void *)rza1_ethernet_nc_memory, 0, sizeof(rza1_ethernet_nc_memory)); + p_memory_top = rza1_ethernet_nc_memory; + + /* Descriptor area configuration */ + p_eth_desc_dsend = (edmac_send_desc_t *)p_memory_top; + p_memory_top += (sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR); + p_eth_desc_drecv = (edmac_recv_desc_t *)p_memory_top; + p_memory_top += (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR); + + /* Transmit descriptor */ + for (i = 0; i < NUM_OF_TX_DESCRIPTOR; i++) { + p_eth_desc_dsend[i].td2 = p_memory_top; /* TD2 TBA */ + p_memory_top += SIZE_OF_BUFFER; + p_eth_desc_dsend[i].td1 = 0; /* TD1 TDL */ + p_eth_desc_dsend[i].td0 = TD0_TFP_TOP_BOTTOM; /* TD0:1frame/1buf1buf, transmission disabled */ + } + p_eth_desc_dsend[i - 1].td0 |= TD0_TDLE; /* Set the last descriptor */ + + /* Receive descriptor */ + for (i = 0; i < NUM_OF_RX_DESCRIPTOR; i++) { + p_eth_desc_drecv[i].rd2 = p_memory_top; /* RD2 RBA */ + p_memory_top += SIZE_OF_BUFFER; + p_eth_desc_drecv[i].rd1 = ((uint32_t)SIZE_OF_BUFFER << 16); /* RD1 RBL */ + p_eth_desc_drecv[i].rd0 = RD0_RACT; /* RD0:reception enabled */ + } + p_eth_desc_drecv[i - 1].rd0 |= RD0_RDLE; /* Set the last descriptor */ + + /* Initialize descriptor management information */ + send_top_index = 0; + recv_top_index = 0; + rx_read_offset = 0; + tx_wite_offset = 0; + p_recv_end_desc = NULL; +} + +static void lan_reg_set(int32_t link) { + /* MAC address setting */ + ETHERMAHR0 = ((uint8_t)mac_addr[0] << 24) + | ((uint8_t)mac_addr[1] << 16) + | ((uint8_t)mac_addr[2] << 8) + | (uint8_t)mac_addr[3]; + ETHERMALR0 = ((uint8_t)mac_addr[4] << 8) + | (uint8_t)mac_addr[5]; + + /* E-DMAC */ + ETHERTDLAR0 = (uint32_t)&p_eth_desc_dsend[0]; + ETHERRDLAR0 = (uint32_t)&p_eth_desc_drecv[0]; + ETHERTDFAR0 = (uint32_t)&p_eth_desc_dsend[0]; + ETHERRDFAR0 = (uint32_t)&p_eth_desc_drecv[0]; + ETHERTDFXR0 = (uint32_t)&p_eth_desc_dsend[NUM_OF_TX_DESCRIPTOR - 1]; + ETHERRDFXR0 = (uint32_t)&p_eth_desc_drecv[NUM_OF_RX_DESCRIPTOR - 1]; + ETHERTDFFR0 |= 0x00000001; /* TDLF Transmit Descriptor Queue Last Flag : Last descriptor (1) */ + ETHERRDFFR0 |= 0x00000001; /* RDLF Receive Descriptor Queue Last Flag : Last descriptor (1) */ + ETHEREDMR0 |= 0x00000040; /* Little endian */ + ETHERTRSCER0 &= ~0x0003009F; /* All clear */ + ETHERTFTR0 &= ~0x000007FF; /* TFT[10:0] Transmit FIFO Threshold : Store and forward modes (H'000) */ + ETHERFDR0 |= 0x00000707; /* Transmit FIFO Size:2048 bytes, Receive FIFO Size:2048 bytes */ + ETHERRMCR0 |= 0x00000001; /* RNC Receive Enable Control : Continuous reception enabled (1) */ + ETHERFCFTR0 &= ~0x001F00FF; + ETHERFCFTR0 |= 0x00070007; + ETHERRPADIR0 &= ~0x001FFFFF; /* Padding Size:No padding insertion, Padding Slot:Inserts at first byte */ + + /* E-MAC */ + ETHERECMR0 &= ~0x04BF2063; /* All clear */ + ETHERRFLR0 &= ~0x0003FFFF; /* RFL[17:0] Receive Frame Length : 1518 bytes (H'00000) */ + ETHERAPR0 &= ~0x0000FFFF; /* AP[15:0] Automatic PAUSE : Flow control is disabled (H'0000) */ + ETHERMPR0 &= ~0x0000FFFF; /* MP[15:0] Manual PAUSE : Flow control is disabled (H'0000) */ + ETHERTPAUSER0 &= ~0x0000FFFF; /* Upper Limit for Automatic PAUSE Frame : Retransmit count is unlimited */ + ETHERCSMR &= ~0xC000003F; /* The result of checksum is not written back to the receive descriptor */ + if ((link == FULL_TX) || (link == FULL_10M) || (link == NEGO_FAIL)) { + ETHERECMR0 |= 0x00000002; /* Set to full-duplex mode */ + } else { + ETHERECMR0 &= ~0x00000002; /* Set to half-duplex mode */ + } + ETHERECMR0 |= 0x00002000; /* MCT = 1 */ + + /* Interrupt-related */ + if (p_recv_cb_fnc != NULL) { + ETHEREESR0 |= 0xFF7F009F; /* Clear all status (by writing 1) */ + ETHEREESIPR0 |= 0x00040000; /* FR Frame Reception (1) */ + ETHERECSR0 |= 0x00000011; /* Clear all status (clear by writing 1) */ + ETHERECSIPR0 &= ~0x00000011; /* PFROIP Disable, ICDIP Disable */ + InterruptHandlerRegister(ETHERI_IRQn, INT_Ether); /* Ethernet interrupt handler registration */ + GIC_SetPriority(ETHERI_IRQn, Interrupt_priority); /* Ethernet interrupt priority */ + GIC_SetConfiguration(ETHERI_IRQn, 1); + GIC_EnableIRQ(ETHERI_IRQn); /* Enables the E-DMAC interrupt */ + } + + ETHERECMR0 |= 0x00000060; /* RE Enable, TE Enable */ + + /* Enable transmission/reception */ + if ((start_stop == 1) && ((ETHEREDRRR0 & 0x00000001) == 0)) { + ETHEREDRRR0 |= 0x00000001; /* RR */ + } +} + +static uint16_t phy_reg_read(uint16_t reg_addr) { + uint16_t data; + + mii_preamble(); + mii_cmd(reg_addr, PHY_READ); + mii_z(); + mii_reg_read(&data); + mii_z(); + + return data; +} + +static void phy_reg_write(uint16_t reg_addr, uint16_t data) { + mii_preamble(); + mii_cmd(reg_addr, PHY_WRITE); + mii_write_1(); + mii_write_0(); + mii_reg_write(data); + mii_z(); +} + +static void mii_preamble(void) { + int32_t i = 32; + + for (i = 32; i > 0; i--) { + /* 1 is output via the MII (Media Independent Interface) block. */ + mii_write_1(); + } +} + +static void mii_cmd(uint16_t reg_addr, uint32_t option) { + int32_t i; + uint16_t data = 0; + + data |= (PHY_ST << 14); /* ST code */ + data |= (option << 12); /* OP code */ + data |= (PHY_ADDR << 7); /* PHY Address */ + data |= (uint16_t)(reg_addr << 2); /* Reg Address */ + for (i = 14; i > 0; i--) { + if ((data & 0x8000) == 0) { + mii_write_0(); + } else { + mii_write_1(); + } + data <<= 1; + } +} + +static void mii_reg_read(uint16_t *data) { + int32_t i; + uint16_t reg_data = 0; + + /* Data are read in one bit at a time */ + for (i = 16; i > 0; i--) { + set_ether_pir(PIR0_MDC_LOW); + set_ether_pir(PIR0_MDC_HIGH); + reg_data <<= 1; + reg_data |= (uint16_t)((ETHERPIR0 & PIR0_MDI) >> 3); /* MDI read */ + set_ether_pir(PIR0_MDC_HIGH); + set_ether_pir(PIR0_MDC_LOW); + } + *data = reg_data; +} + +static void mii_reg_write(uint16_t data) { + int32_t i; + + /* Data are written one bit at a time */ + for (i = 16; i > 0; i--) { + if ((data & 0x8000) == 0) { + mii_write_0(); + } else { + mii_write_1(); + } + data <<= 1; + } +} + +static void mii_z(void) { + set_ether_pir(PIR0_MDC_LOW); + set_ether_pir(PIR0_MDC_HIGH); + set_ether_pir(PIR0_MDC_HIGH); + set_ether_pir(PIR0_MDC_LOW); +} + +static void mii_write_1(void) { + set_ether_pir(PIR0_MDO | PIR0_MMD); + set_ether_pir(PIR0_MDO | PIR0_MMD | PIR0_MDC); + set_ether_pir(PIR0_MDO | PIR0_MMD | PIR0_MDC); + set_ether_pir(PIR0_MDO | PIR0_MMD); +} + +static void mii_write_0(void) { + set_ether_pir(PIR0_MMD); + set_ether_pir(PIR0_MMD | PIR0_MDC); + set_ether_pir(PIR0_MMD | PIR0_MDC); + set_ether_pir(PIR0_MMD); +} + +static void set_ether_pir(uint32_t set_data) { + int32_t i; + + for (i = MDC_WAIT; i > 0; i--) { + ETHERPIR0 = set_data; + } +} + +static void wait_100us(int32_t wait_cnt) { + volatile int32_t j = LOOP_100us * wait_cnt; + + while (--j) { + /* Do Nothing */ + } +} +#endif /* DEVICE_ETHERNET */ diff --git a/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.h b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.h new file mode 100644 index 0000000..3553879 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth.h @@ -0,0 +1,65 @@ +/* Copyright (c) 2020 Renesas Electronics Corporation. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBED_ETHERNET_API_H +#define MBED_ETHERNET_API_H + +#include "device.h" +#include "platform/mbed_toolchain.h" + +#if DEVICE_ETHERNET + +#ifdef __cplusplus +extern "C" { +#endif + +// Connection constants +int rza1_ethernet_init(void); +void rza1_ethernet_free(void); + +// write size bytes from data to ethernet buffer +// return num bytes written +// or -1 if size is too big +int rza1_ethernet_write(const char *data, int size); + +// send ethernet write buffer, returning the packet size sent +int rza1_ethernet_send(void); + +// receive from ethernet buffer, returning packet size, or 0 if no packet +int rza1_ethernet_receive(void); + +// read size bytes in to data, return actual num bytes read (0..size) +// if data == NULL, throw the bytes away +int rza1_ethernet_read(char *data, int size); + +// get the ethernet address +void rza1_ethernet_address(char *mac); + +// see if the link is up +int rza1_ethernet_link(void); + +// force link settings +void rza1_ethernet_set_link(int speed, int duplex); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + + +/** @}*/ diff --git a/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth_ext.h b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth_ext.h new file mode 100644 index 0000000..e61a15f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_RZ_A1_EMAC/rza1_eth_ext.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2020 Renesas Electronics Corporation. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ETHERNETEXT_H +#define ETHERNETEXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* PHY link mode */ +#define NEGO_FAIL (0) +#define HALF_10M (1) +#define FULL_10M (2) +#define HALF_TX (3) +#define FULL_TX (4) + +typedef void (ethernetext_cb_fnc)(void); + +typedef struct tag_rza1_ethernet_cfg { + int int_priority; + ethernetext_cb_fnc *recv_cb; + char *ether_mac; +} rza1_ethernet_cfg_t; + +extern int ethernetext_init(rza1_ethernet_cfg_t *p_ethcfg); +extern void ethernetext_start_stop(int32_t mode); +extern int ethernetext_chk_link_mode(void); +extern void ethernetext_set_link_mode(int32_t link); +extern void ethernetext_add_multicast_group(const uint8_t *addr); +extern void ethernetext_remove_multicast_group(const uint8_t *addr); +extern void ethernetext_set_all_multicast(int all); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c new file mode 100644 index 0000000..7b054c7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c @@ -0,0 +1,119 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f2xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c new file mode 100644 index 0000000..dd004db --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stm32f2xx_hal.h" + +void _eth_config_mac(ETH_HandleTypeDef *heth) +{ + ETH_MACInitTypeDef macconf = { + .Watchdog = ETH_WATCHDOG_ENABLE, + .Jabber = ETH_JABBER_ENABLE, + .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, + .CarrierSense = ETH_CARRIERSENCE_ENABLE, + .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, + .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, + .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, + .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, + .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, + .BackOffLimit = ETH_BACKOFFLIMIT_10, + .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, + .ReceiveAll = ETH_RECEIVEAll_DISABLE, + .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, + .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, + .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, + .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, + .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, + .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter + .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, + .HashTableHigh = 0x0U, + .HashTableLow = 0x0U, + .PauseTime = 0x0U, + .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, + .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, + .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, + .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, + .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, + .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, + .VLANTagIdentifier = 0x0U + }; + + if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } else { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + + (void) HAL_ETH_ConfigMAC(heth, &macconf); +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h new file mode 100644 index 0000000..c4fe5e7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define ETH_IP_VERSION_V1 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c new file mode 100644 index 0000000..a11be4a --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stm32f4xx_hal.h" + +void _eth_config_mac(ETH_HandleTypeDef *heth) +{ + ETH_MACInitTypeDef macconf = { + .Watchdog = ETH_WATCHDOG_ENABLE, + .Jabber = ETH_JABBER_ENABLE, + .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, + .CarrierSense = ETH_CARRIERSENCE_ENABLE, + .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, + .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, + .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, + .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, + .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, + .BackOffLimit = ETH_BACKOFFLIMIT_10, + .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, + .ReceiveAll = ETH_RECEIVEAll_DISABLE, + .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, + .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, + .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, + .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, + .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, + .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter + .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, + .HashTableHigh = 0x0U, + .HashTableLow = 0x0U, + .PauseTime = 0x0U, + .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, + .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, + .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, + .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, + .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, + .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, + .VLANTagIdentifier = 0x0U, + }; + + if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } else { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + + (void) HAL_ETH_ConfigMAC(heth, &macconf); +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c new file mode 100644 index 0000000..a95ea0f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c @@ -0,0 +1,81 @@ +#include "stm32f4xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> + RMII_MII_TX_EN --------------------> PB11 + RMII_MII_TXD0 ---------------------> PB12 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB11, PB12 and PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> + RMII_MII_TX_EN --------------------> PB11 + RMII_MII_TXD0 ---------------------> PB12 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c new file mode 100644 index 0000000..a11be4a --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stm32f4xx_hal.h" + +void _eth_config_mac(ETH_HandleTypeDef *heth) +{ + ETH_MACInitTypeDef macconf = { + .Watchdog = ETH_WATCHDOG_ENABLE, + .Jabber = ETH_JABBER_ENABLE, + .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, + .CarrierSense = ETH_CARRIERSENCE_ENABLE, + .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, + .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, + .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, + .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, + .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, + .BackOffLimit = ETH_BACKOFFLIMIT_10, + .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, + .ReceiveAll = ETH_RECEIVEAll_DISABLE, + .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, + .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, + .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, + .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, + .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, + .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter + .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, + .HashTableHigh = 0x0U, + .HashTableLow = 0x0U, + .PauseTime = 0x0U, + .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, + .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, + .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, + .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, + .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, + .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, + .VLANTagIdentifier = 0x0U, + }; + + if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } else { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + + (void) HAL_ETH_ConfigMAC(heth, &macconf); +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c new file mode 100644 index 0000000..09dfb94 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c @@ -0,0 +1,119 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f4xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c new file mode 100644 index 0000000..a11be4a --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stm32f4xx_hal.h" + +void _eth_config_mac(ETH_HandleTypeDef *heth) +{ + ETH_MACInitTypeDef macconf = { + .Watchdog = ETH_WATCHDOG_ENABLE, + .Jabber = ETH_JABBER_ENABLE, + .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, + .CarrierSense = ETH_CARRIERSENCE_ENABLE, + .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, + .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, + .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, + .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, + .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, + .BackOffLimit = ETH_BACKOFFLIMIT_10, + .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, + .ReceiveAll = ETH_RECEIVEAll_DISABLE, + .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, + .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, + .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, + .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, + .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, + .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter + .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, + .HashTableHigh = 0x0U, + .HashTableLow = 0x0U, + .PauseTime = 0x0U, + .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, + .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, + .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, + .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, + .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, + .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, + .VLANTagIdentifier = 0x0U, + }; + + if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } else { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + + (void) HAL_ETH_ConfigMAC(heth, &macconf); +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c new file mode 100644 index 0000000..09dfb94 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c @@ -0,0 +1,119 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f4xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h new file mode 100644 index 0000000..c4fe5e7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define ETH_IP_VERSION_V1 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c new file mode 100644 index 0000000..b0a2aec --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c @@ -0,0 +1,115 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f7xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + /* Disable DCache for STM32F7 family */ + SCB_DisableDCache(); + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PG14 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11, PG13 and PG14 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PG14 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c new file mode 100644 index 0000000..de64941 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c @@ -0,0 +1,121 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f7xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + /* Disable DCache for STM32F7 family */ + SCB_DisableDCache(); + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PD5 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PG14 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PD5 */ + GPIO_InitStructure.Pin = GPIO_PIN_5; + HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); + + /* Configure PG11, PG13 and PG14 */ + GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PD5 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PG14 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c new file mode 100644 index 0000000..019898b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c @@ -0,0 +1,121 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f7xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + /* Disable DCache for STM32F7 family */ + SCB_DisableDCache(); + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c new file mode 100644 index 0000000..019898b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c @@ -0,0 +1,121 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f7xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + /* Disable DCache for STM32F7 family */ + SCB_DisableDCache(); + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c new file mode 100644 index 0000000..019898b --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c @@ -0,0 +1,121 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32f7xx_hal.h" + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStructure; + if (heth->Instance == ETH) { + /* Disable DCache for STM32F7 family */ + SCB_DisableDCache(); + + /* Enable GPIOs clocks */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + /* Configure PA1, PA2 and PA7 */ + GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; + GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Alternate = GPIO_AF11_ETH; + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); + + /* Configure PB13 */ + GPIO_InitStructure.Pin = GPIO_PIN_13; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + /* Configure PC1, PC4 and PC5 */ + GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + /* Configure PG2, PG11 and PG13 */ + GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; + HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); + + /* Enable the Ethernet global Interrupt */ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); + + /* Enable ETHERNET clock */ + __HAL_RCC_ETH_CLK_ENABLE(); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH_CLK_DISABLE(); + + /** ETH GPIO Configuration + RMII_REF_CLK ----------------------> PA1 + RMII_MDIO -------------------------> PA2 + RMII_MDC --------------------------> PC1 + RMII_MII_CRS_DV -------------------> PA7 + RMII_MII_RXD0 ---------------------> PC4 + RMII_MII_RXD1 ---------------------> PC5 + RMII_MII_RXER ---------------------> PG2 + RMII_MII_TX_EN --------------------> PG11 + RMII_MII_TXD0 ---------------------> PG13 + RMII_MII_TXD1 ---------------------> PB13 + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); + HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); + + /* Disable the Ethernet global Interrupt */ + NVIC_DisableIRQ(ETH_IRQn); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c new file mode 100644 index 0000000..76dbeb4 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c @@ -0,0 +1,60 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stm32f7xx_hal.h" + +void _eth_config_mac(ETH_HandleTypeDef *heth) +{ + ETH_MACInitTypeDef macconf = { + .Watchdog = ETH_WATCHDOG_ENABLE, + .Jabber = ETH_JABBER_ENABLE, + .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, + .CarrierSense = ETH_CARRIERSENCE_ENABLE, + .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, + .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, + .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, + .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, + .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, + .BackOffLimit = ETH_BACKOFFLIMIT_10, + .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, + .ReceiveAll = ETH_RECEIVEAll_DISABLE, + .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, + .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, + .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, + .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, + .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, + .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter + .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, + .HashTableHigh = 0x0, + .HashTableLow = 0x0, + .PauseTime = 0x0, + .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, + .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, + .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, + .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, + .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, + .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, + .VLANTagIdentifier = 0x0 + }; + + if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; + } else { + macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; + } + + (void) HAL_ETH_ConfigMAC(heth, &macconf); +} diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h new file mode 100644 index 0000000..c4fe5e7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define ETH_IP_VERSION_V1 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c new file mode 100644 index 0000000..5255724 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c @@ -0,0 +1,149 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define ETHERNET 1 +#if (MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == ETHERNET) +#if !defined(DISCO_H747I_ETHERNET_SOLDERBRIGE) +#error Hardware modifications are required for Ethernet on DISCO_H747I. see https://os.mbed.com/teams/ST/wiki/DISCO_H747I-modifications-for-Ethernet +#endif +#endif + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32h7xx_hal.h" + +#define ETH_TX_EN_Pin GPIO_PIN_11 +#define ETH_TX_EN_GPIO_Port GPIOG +#define ETH_TXD1_Pin GPIO_PIN_12 +#define ETH_TXD1_GPIO_Port GPIOG +#define ETH_TXD0_Pin GPIO_PIN_13 +#define ETH_TXD0_GPIO_Port GPIOG +#define ETH_MDC_SAI4_D1_Pin GPIO_PIN_1 +#define ETH_MDC_SAI4_D1_GPIO_Port GPIOC +#define ETH_MDIO_Pin GPIO_PIN_2 +#define ETH_MDIO_GPIO_Port GPIOA +#define ETH_REF_CLK_Pin GPIO_PIN_1 +#define ETH_REF_CLK_GPIO_Port GPIOA +#define ETH_CRS_DV_Pin GPIO_PIN_7 +#define ETH_CRS_DV_GPIO_Port GPIOA +#define ETH_RXD0_Pin GPIO_PIN_4 +#define ETH_RXD0_GPIO_Port GPIOC +#define ETH_RXD1_Pin GPIO_PIN_5 +#define ETH_RXD1_GPIO_Port GPIOC + + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if (heth->Instance == ETH) { +#if defined(CORE_CM7) + /* Disable DCache for STM32H7 family */ + SCB_DisableDCache(); +#endif + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + // __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + // __HAL_RCC_GPIOH_CLK_ENABLE(); + + /* Enable Peripheral clock */ + __HAL_RCC_ETH1MAC_CLK_ENABLE(); + __HAL_RCC_ETH1TX_CLK_ENABLE(); + __HAL_RCC_ETH1RX_CLK_ENABLE(); + + /**ETH GPIO Configuration + PG11 ------> ETH_TX_EN + PG12 ------> ETH_TXD1 + PG13 ------> ETH_TXD0 + PC1 ------> ETH_MDC + PA2 ------> ETH_MDIO + PA1 ------> ETH_REF_CLK + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + */ + GPIO_InitStruct.Pin = ETH_TX_EN_Pin | ETH_TXD1_Pin | ETH_TXD0_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = ETH_MDC_SAI4_D1_Pin | ETH_RXD0_Pin | ETH_RXD1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = ETH_MDIO_Pin | ETH_REF_CLK_Pin | ETH_CRS_DV_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Peripheral clock disable */ + __HAL_RCC_ETH1MAC_CLK_DISABLE(); + __HAL_RCC_ETH1TX_CLK_DISABLE(); + __HAL_RCC_ETH1RX_CLK_DISABLE(); + + /**ETH GPIO Configuration + PG11 ------> ETH_TX_EN + PG12 ------> ETH_TXD1 + PG13 ------> ETH_TXD0 + PC1 ------> ETH_MDC + PA2 ------> ETH_MDIO + PA1 ------> ETH_REF_CLK + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + */ + HAL_GPIO_DeInit(GPIOG, ETH_TX_EN_Pin | ETH_TXD1_Pin | ETH_TXD0_Pin); + + HAL_GPIO_DeInit(GPIOC, ETH_MDC_SAI4_D1_Pin | ETH_RXD0_Pin | ETH_RXD1_Pin); + + HAL_GPIO_DeInit(GPIOA, ETH_MDIO_Pin | ETH_REF_CLK_Pin | ETH_CRS_DV_Pin); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c new file mode 100644 index 0000000..8c71ec7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c @@ -0,0 +1,160 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32h7xx_hal.h" + +#define MCO_Pin GPIO_PIN_0 +#define MCO_GPIO_Port GPIOH +#define RMII_MDC_Pin GPIO_PIN_1 +#define RMII_MDC_GPIO_Port GPIOC +#define RMII_REF_CLK_Pin GPIO_PIN_1 +#define RMII_REF_CLK_GPIO_Port GPIOA +#define RMII_MDIO_Pin GPIO_PIN_2 +#define RMII_MDIO_GPIO_Port GPIOA +#define RMII_CRS_DV_Pin GPIO_PIN_7 +#define RMII_CRS_DV_GPIO_Port GPIOA +#define RMII_RXD0_Pin GPIO_PIN_4 +#define RMII_RXD0_GPIO_Port GPIOC +#define RMII_RXD1_Pin GPIO_PIN_5 +#define RMII_RXD1_GPIO_Port GPIOC +#define RMII_TXD1_Pin GPIO_PIN_13 +#define RMII_TXD1_GPIO_Port GPIOB +#define TMS_Pin GPIO_PIN_13 +#define TMS_GPIO_Port GPIOA +#define TCK_Pin GPIO_PIN_14 +#define TCK_GPIO_Port GPIOA +#define RMII_TX_EN_Pin GPIO_PIN_11 +#define RMII_TX_EN_GPIO_Port GPIOG +#define RMII_TXD0_Pin GPIO_PIN_13 +#define RMII_TXD0_GPIO_Port GPIOG + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if (heth->Instance == ETH) { + /* Disable DCache for STM32H7 family */ + SCB_DisableDCache(); + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /* Enable Peripheral clock */ + __HAL_RCC_ETH1MAC_CLK_ENABLE(); + __HAL_RCC_ETH1TX_CLK_ENABLE(); + __HAL_RCC_ETH1RX_CLK_ENABLE(); + + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB13 ------> ETH_TXD1 + PG11 ------> ETH_TX_EN + PG13 ------> ETH_TXD0 + */ + GPIO_InitStruct.Pin = RMII_MDC_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(RMII_MDC_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_RXD0_Pin | RMII_RXD1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_TXD1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_TX_EN_Pin | RMII_TXD0_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Disable Peripheral clock */ + __HAL_RCC_ETH1MAC_CLK_DISABLE(); + __HAL_RCC_ETH1TX_CLK_DISABLE(); + __HAL_RCC_ETH1RX_CLK_DISABLE(); + + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB13 ------> ETH_TXD1 + PG11 ------> ETH_TX_EN + PG13 ------> ETH_TXD0 + */ + HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin); + + HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin); + + HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin); + + HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin | RMII_TXD0_Pin); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c new file mode 100644 index 0000000..8c71ec7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c @@ -0,0 +1,160 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018, STMicroelectronics + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT + +#include "stm32h7xx_hal.h" + +#define MCO_Pin GPIO_PIN_0 +#define MCO_GPIO_Port GPIOH +#define RMII_MDC_Pin GPIO_PIN_1 +#define RMII_MDC_GPIO_Port GPIOC +#define RMII_REF_CLK_Pin GPIO_PIN_1 +#define RMII_REF_CLK_GPIO_Port GPIOA +#define RMII_MDIO_Pin GPIO_PIN_2 +#define RMII_MDIO_GPIO_Port GPIOA +#define RMII_CRS_DV_Pin GPIO_PIN_7 +#define RMII_CRS_DV_GPIO_Port GPIOA +#define RMII_RXD0_Pin GPIO_PIN_4 +#define RMII_RXD0_GPIO_Port GPIOC +#define RMII_RXD1_Pin GPIO_PIN_5 +#define RMII_RXD1_GPIO_Port GPIOC +#define RMII_TXD1_Pin GPIO_PIN_13 +#define RMII_TXD1_GPIO_Port GPIOB +#define TMS_Pin GPIO_PIN_13 +#define TMS_GPIO_Port GPIOA +#define TCK_Pin GPIO_PIN_14 +#define TCK_GPIO_Port GPIOA +#define RMII_TX_EN_Pin GPIO_PIN_11 +#define RMII_TX_EN_GPIO_Port GPIOG +#define RMII_TXD0_Pin GPIO_PIN_13 +#define RMII_TXD0_GPIO_Port GPIOG + +/** + * Override HAL Eth Init function + */ +void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if (heth->Instance == ETH) { + /* Disable DCache for STM32H7 family */ + SCB_DisableDCache(); + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + + /* Enable Peripheral clock */ + __HAL_RCC_ETH1MAC_CLK_ENABLE(); + __HAL_RCC_ETH1TX_CLK_ENABLE(); + __HAL_RCC_ETH1RX_CLK_ENABLE(); + + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB13 ------> ETH_TXD1 + PG11 ------> ETH_TX_EN + PG13 ------> ETH_TXD0 + */ + GPIO_InitStruct.Pin = RMII_MDC_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(RMII_MDC_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_RXD0_Pin | RMII_RXD1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_TXD1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = RMII_TX_EN_Pin | RMII_TXD0_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF11_ETH; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + } +} + +/** + * Override HAL Eth DeInit function + */ +void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) +{ + if (heth->Instance == ETH) { + /* Disable Peripheral clock */ + __HAL_RCC_ETH1MAC_CLK_DISABLE(); + __HAL_RCC_ETH1TX_CLK_DISABLE(); + __HAL_RCC_ETH1RX_CLK_DISABLE(); + + /**ETH GPIO Configuration + PC1 ------> ETH_MDC + PA1 ------> ETH_REF_CLK + PA2 ------> ETH_MDIO + PA7 ------> ETH_CRS_DV + PC4 ------> ETH_RXD0 + PC5 ------> ETH_RXD1 + PB13 ------> ETH_TXD1 + PG11 ------> ETH_TX_EN + PG13 ------> ETH_TXD0 + */ + HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin); + + HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin); + + HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin); + + HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin | RMII_TXD0_Pin); + } +} + +#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c new file mode 100644 index 0000000..0fd341c --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c @@ -0,0 +1,590 @@ +/** + ****************************************************************************** + * @file lan8742.c + * @author MCD Application Team + * @version V1.0.0 + * @date 08-March-2017 + * @brief This file provides a set of functions needed to manage the LAN742 + * PHY devices. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "lan8742.h" + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @defgroup LAN8742 LAN8742 + * @{ + */ + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines + * @{ + */ +#define LAN8742_SW_RESET_TO ((uint32_t)500U) +#define LAN8742_INIT_TO ((uint32_t)2000U) +#define LAN8742_MAX_DEV_ADDR ((uint32_t)31U) +/** + * @} + */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions + * @{ + */ + +/** + * @brief Register IO functions to component object + * @param pObj: device object of LAN8742_Object_t. + * @param ioctx: holds device IO functions. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_ERROR if missing mandatory function + */ +int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx) +{ + if (!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick) { + return LAN8742_STATUS_ERROR; + } + + pObj->IO.Init = ioctx->Init; + pObj->IO.DeInit = ioctx->DeInit; + pObj->IO.ReadReg = ioctx->ReadReg; + pObj->IO.WriteReg = ioctx->WriteReg; + pObj->IO.GetTick = ioctx->GetTick; + + return LAN8742_STATUS_OK; +} + +/** + * @brief Initialize the lan8742 and configure the needed hardware resources + * @param pObj: device object LAN8742_Object_t. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_ADDRESS_ERROR if cannot find device address + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + * LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset + */ +int32_t LAN8742_Init(lan8742_Object_t *pObj) +{ + uint32_t tickstart = 0, regvalue = 0, addr = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->Is_Initialized == 0) { + if (pObj->IO.Init != 0) { + /* GPIO and Clocks initialization */ + pObj->IO.Init(); + } + + /* for later check */ + pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1; + + /* Get the device address from special mode register */ + for (addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++) { + if (pObj->IO.ReadReg(addr, LAN8742_SMR, ®value) < 0) { + status = LAN8742_STATUS_READ_ERROR; + /* Can't read from this device address + continue with next address */ + continue; + } + + if ((regvalue & LAN8742_SMR_PHY_ADDR) == addr) { + pObj->DevAddr = addr; + status = LAN8742_STATUS_OK; + break; + } + } + + if (pObj->DevAddr > LAN8742_MAX_DEV_ADDR) { + status = LAN8742_STATUS_ADDRESS_ERROR; + } + + /* if device address is matched */ + if (status == LAN8742_STATUS_OK) { + /* set a software reset */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0) { + /* get software reset status */ + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) >= 0) { + tickstart = pObj->IO.GetTick(); + + /* wait until software reset is done or timeout occured */ + while (regvalue & LAN8742_BCR_SOFT_RESET) { + if ((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO) { + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) < 0) { + status = LAN8742_STATUS_READ_ERROR; + break; + } + } else { + status = LAN8742_STATUS_RESET_TIMEOUT; + } + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + } else { + status = LAN8742_STATUS_WRITE_ERROR; + } + } + } + + if (status == LAN8742_STATUS_OK) { + tickstart = pObj->IO.GetTick(); + + /* Wait for 2s to perform initialization */ + while ((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO) { + } + pObj->Is_Initialized = 1; + } + + return status; +} + +/** + * @brief De-Initialize the lan8742 and it's hardware resources + * @param pObj: device object LAN8742_Object_t. + * @retval None + */ +int32_t LAN8742_DeInit(lan8742_Object_t *pObj) +{ + if (pObj->Is_Initialized) { + if (pObj->IO.DeInit != 0) { + if (pObj->IO.DeInit() < 0) { + return LAN8742_STATUS_ERROR; + } + } + + pObj->Is_Initialized = 0; + } + + return LAN8742_STATUS_OK; +} + +/** + * @brief Disable the LAN8742 power down mode. + * @param pObj: device object LAN8742_Object_t. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { + readval &= ~LAN8742_BCR_POWER_DOWN; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Enable the LAN8742 power down mode. + * @param pObj: device object LAN8742_Object_t. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { + readval |= LAN8742_BCR_POWER_DOWN; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Start the auto negotiation process. + * @param pObj: device object LAN8742_Object_t. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { + readval |= LAN8742_BCR_AUTONEGO_EN; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Get the link state of LAN8742 device. + * @param pObj: Pointer to device object. + * @param pLinkState: Pointer to link state + * @retval LAN8742_STATUS_LINK_DOWN if link is down + * LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed + * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD + * LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD + * LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD + * LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + + /* Read Status register */ + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { + return LAN8742_STATUS_READ_ERROR; + } + + /* Read Status register again */ + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { + return LAN8742_STATUS_READ_ERROR; + } + + if ((readval & LAN8742_BSR_LINK_STATUS) == 0) { + /* Return Link Down status */ + return LAN8742_STATUS_LINK_DOWN; + } + + /* Check Auto negotiaition */ + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0) { + return LAN8742_STATUS_READ_ERROR; + } + + if ((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN) { + if (((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) { + return LAN8742_STATUS_100MBITS_FULLDUPLEX; + } else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) { + return LAN8742_STATUS_100MBITS_HALFDUPLEX; + } else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE) { + return LAN8742_STATUS_10MBITS_FULLDUPLEX; + } else { + return LAN8742_STATUS_10MBITS_HALFDUPLEX; + } + } else { /* Auto Nego enabled */ + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0) { + return LAN8742_STATUS_READ_ERROR; + } + + /* Check if auto nego not done */ + if ((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0) { + return LAN8742_STATUS_AUTONEGO_NOTDONE; + } + + if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD) { + return LAN8742_STATUS_100MBITS_FULLDUPLEX; + } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD) { + return LAN8742_STATUS_100MBITS_HALFDUPLEX; + } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD) { + return LAN8742_STATUS_10MBITS_FULLDUPLEX; + } else { + return LAN8742_STATUS_10MBITS_HALFDUPLEX; + } + } +} + +/** + * @brief Set the link state of LAN8742 device. + * @param pObj: Pointer to device object. + * @param pLinkState: link state can be one of the following + * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD + * LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD + * LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD + * LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_ERROR if parameter error + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState) +{ + uint32_t bcrvalue = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0) { + /* Disable link config (Auto nego, speed and duplex) */ + bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE); + + if (LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX) { + bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE); + } else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX) { + bcrvalue |= LAN8742_BCR_SPEED_SELECT; + } else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX) { + bcrvalue |= LAN8742_BCR_DUPLEX_MODE; + } else { + /* Wrong link status parameter */ + status = LAN8742_STATUS_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + if (status == LAN8742_STATUS_OK) { + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } + + return status; +} + +/** + * @brief Enable loopback mode. + * @param pObj: Pointer to device object. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { + readval |= LAN8742_BCR_LOOPBACK; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Disable loopback mode. + * @param pObj: Pointer to device object. + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { + readval &= ~LAN8742_BCR_LOOPBACK; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Enable IT source. + * @param pObj: Pointer to device object. + * @param Interrupt: IT source to be enabled + * should be a value or a combination of the following: + * LAN8742_WOL_IT + * LAN8742_ENERGYON_IT + * LAN8742_AUTONEGO_COMPLETE_IT + * LAN8742_REMOTE_FAULT_IT + * LAN8742_LINK_DOWN_IT + * LAN8742_AUTONEGO_LP_ACK_IT + * LAN8742_PARALLEL_DETECTION_FAULT_IT + * LAN8742_AUTONEGO_PAGE_RECEIVED_IT + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0) { + readval |= Interrupt; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Disable IT source. + * @param pObj: Pointer to device object. + * @param Interrupt: IT source to be disabled + * should be a value or a combination of the following: + * LAN8742_WOL_IT + * LAN8742_ENERGYON_IT + * LAN8742_AUTONEGO_COMPLETE_IT + * LAN8742_REMOTE_FAULT_IT + * LAN8742_LINK_DOWN_IT + * LAN8742_AUTONEGO_LP_ACK_IT + * LAN8742_PARALLEL_DETECTION_FAULT_IT + * LAN8742_AUTONEGO_PAGE_RECEIVED_IT + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + * LAN8742_STATUS_WRITE_ERROR if connot write to register + */ +int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0) { + readval &= ~Interrupt; + + /* Apply configuration */ + if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0) { + status = LAN8742_STATUS_WRITE_ERROR; + } + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Clear IT flag. + * @param pObj: Pointer to device object. + * @param Interrupt: IT flag to be cleared + * should be a value or a combination of the following: + * LAN8742_WOL_IT + * LAN8742_ENERGYON_IT + * LAN8742_AUTONEGO_COMPLETE_IT + * LAN8742_REMOTE_FAULT_IT + * LAN8742_LINK_DOWN_IT + * LAN8742_AUTONEGO_LP_ACK_IT + * LAN8742_PARALLEL_DETECTION_FAULT_IT + * LAN8742_AUTONEGO_PAGE_RECEIVED_IT + * @retval LAN8742_STATUS_OK if OK + * LAN8742_STATUS_READ_ERROR if connot read register + */ +int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = LAN8742_STATUS_OK; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0) { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @brief Get IT Flag status. + * @param pObj: Pointer to device object. + * @param Interrupt: IT Flag to be checked, + * should be a value or a combination of the following: + * LAN8742_WOL_IT + * LAN8742_ENERGYON_IT + * LAN8742_AUTONEGO_COMPLETE_IT + * LAN8742_REMOTE_FAULT_IT + * LAN8742_LINK_DOWN_IT + * LAN8742_AUTONEGO_LP_ACK_IT + * LAN8742_PARALLEL_DETECTION_FAULT_IT + * LAN8742_AUTONEGO_PAGE_RECEIVED_IT + * @retval 1 IT flag is SET + * 0 IT flag is RESET + * LAN8742_STATUS_READ_ERROR if connot read register + */ +int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt) +{ + uint32_t readval = 0; + int32_t status = 0; + + if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0) { + status = ((readval & Interrupt) == Interrupt); + } else { + status = LAN8742_STATUS_READ_ERROR; + } + + return status; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h new file mode 100644 index 0000000..0214cff --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h @@ -0,0 +1,464 @@ +/** + ****************************************************************************** + * @file lan8742.h + * @author MCD Application Team + * @version V1.0.0 + * @date 08-March-2017 + * @brief This file contains all the functions prototypes for the + * lan8742.c PHY driver. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2017 STMicroelectronics

+ * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __LAN8742_H +#define __LAN8742_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include + +/** @addtogroup BSP + * @{ + */ + +/** @addtogroup Component + * @{ + */ + +/** @defgroup LAN8742 + * @{ + */ +/* Exported constants --------------------------------------------------------*/ +/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants + * @{ + */ + +/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping + * @{ + */ +#define LAN8742_BCR ((uint16_t)0x0000U) +#define LAN8742_BSR ((uint16_t)0x0001U) +#define LAN8742_PHYI1R ((uint16_t)0x0002U) +#define LAN8742_PHYI2R ((uint16_t)0x0003U) +#define LAN8742_ANAR ((uint16_t)0x0004U) +#define LAN8742_ANLPAR ((uint16_t)0x0005U) +#define LAN8742_ANER ((uint16_t)0x0006U) +#define LAN8742_ANNPTR ((uint16_t)0x0007U) +#define LAN8742_ANNPRR ((uint16_t)0x0008U) +#define LAN8742_MMDACR ((uint16_t)0x000DU) +#define LAN8742_MMDAADR ((uint16_t)0x000EU) +#define LAN8742_ENCTR ((uint16_t)0x0010U) +#define LAN8742_MCSR ((uint16_t)0x0011U) +#define LAN8742_SMR ((uint16_t)0x0012U) +#define LAN8742_TPDCR ((uint16_t)0x0018U) +#define LAN8742_TCSR ((uint16_t)0x0019U) +#define LAN8742_SECR ((uint16_t)0x001AU) +#define LAN8742_SCSIR ((uint16_t)0x001BU) +#define LAN8742_CLR ((uint16_t)0x001CU) +#define LAN8742_ISFR ((uint16_t)0x001DU) +#define LAN8742_IMR ((uint16_t)0x001EU) +#define LAN8742_PHYSCSR ((uint16_t)0x001FU) +/** + * @} + */ + +/** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition + * @{ + */ +#define LAN8742_BCR_SOFT_RESET ((uint16_t)0x8000U) +#define LAN8742_BCR_LOOPBACK ((uint16_t)0x4000U) +#define LAN8742_BCR_SPEED_SELECT ((uint16_t)0x2000U) +#define LAN8742_BCR_AUTONEGO_EN ((uint16_t)0x1000U) +#define LAN8742_BCR_POWER_DOWN ((uint16_t)0x0800U) +#define LAN8742_BCR_ISOLATE ((uint16_t)0x0400U) +#define LAN8742_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U) +#define LAN8742_BCR_DUPLEX_MODE ((uint16_t)0x0100U) +/** + * @} + */ + +/** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition + * @{ + */ +#define LAN8742_BSR_100BASE_T4 ((uint16_t)0x8000U) +#define LAN8742_BSR_100BASE_TX_FD ((uint16_t)0x4000U) +#define LAN8742_BSR_100BASE_TX_HD ((uint16_t)0x2000U) +#define LAN8742_BSR_10BASE_T_FD ((uint16_t)0x1000U) +#define LAN8742_BSR_10BASE_T_HD ((uint16_t)0x0800U) +#define LAN8742_BSR_100BASE_T2_FD ((uint16_t)0x0400U) +#define LAN8742_BSR_100BASE_T2_HD ((uint16_t)0x0200U) +#define LAN8742_BSR_EXTENDED_STATUS ((uint16_t)0x0100U) +#define LAN8742_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U) +#define LAN8742_BSR_REMOTE_FAULT ((uint16_t)0x0010U) +#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U) +#define LAN8742_BSR_LINK_STATUS ((uint16_t)0x0004U) +#define LAN8742_BSR_JABBER_DETECT ((uint16_t)0x0002U) +#define LAN8742_BSR_EXTENDED_CAP ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition + * @{ + */ +#define LAN8742_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU) +/** + * @} + */ + +/** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition + * @{ + */ +#define LAN8742_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U) +#define LAN8742_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U) +#define LAN8742_PHYI2R_REVISION_NBR ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition + * @{ + */ +#define LAN8742_ANAR_NEXT_PAGE ((uint16_t)0x8000U) +#define LAN8742_ANAR_REMOTE_FAULT ((uint16_t)0x2000U) +#define LAN8742_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U) +#define LAN8742_ANAR_PO_NOPAUSE ((uint16_t)0x0000U) +#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) +#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) +#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) +#define LAN8742_ANAR_100BASE_TX_FD ((uint16_t)0x0100U) +#define LAN8742_ANAR_100BASE_TX ((uint16_t)0x0080U) +#define LAN8742_ANAR_10BASE_T_FD ((uint16_t)0x0040U) +#define LAN8742_ANAR_10BASE_T ((uint16_t)0x0020U) +#define LAN8742_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition + * @{ + */ +#define LAN8742_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U) +#define LAN8742_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U) +#define LAN8742_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U) +#define LAN8742_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U) +#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) +#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) +#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) +#define LAN8742_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U) +#define LAN8742_ANLPAR_100BASE_TX ((uint16_t)0x0080U) +#define LAN8742_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U) +#define LAN8742_ANLPAR_10BASE_T ((uint16_t)0x0020U) +#define LAN8742_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU) +/** + * @} + */ + +/** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition + * @{ + */ +#define LAN8742_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U) +#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U) +#define LAN8742_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U) +#define LAN8742_ANER_LP_NP_ABLE ((uint16_t)0x0008U) +#define LAN8742_ANER_NP_ABLE ((uint16_t)0x0004U) +#define LAN8742_ANER_PAGE_RECEIVED ((uint16_t)0x0002U) +#define LAN8742_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition + * @{ + */ +#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U) +#define LAN8742_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U) +#define LAN8742_ANNPTR_ACK2 ((uint16_t)0x1000U) +#define LAN8742_ANNPTR_TOGGLE ((uint16_t)0x0800U) +#define LAN8742_ANNPTR_MESSAGGE_CODE ((uint16_t)0x07FFU) +/** + * @} + */ + +/** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition + * @{ + */ +#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U) +#define LAN8742_ANNPRR_ACK ((uint16_t)0x4000U) +#define LAN8742_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U) +#define LAN8742_ANNPRR_ACK2 ((uint16_t)0x1000U) +#define LAN8742_ANNPRR_TOGGLE ((uint16_t)0x0800U) +#define LAN8742_ANNPRR_MESSAGGE_CODE ((uint16_t)0x07FFU) +/** + * @} + */ + +/** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition + * @{ + */ +#define LAN8742_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U) +#define LAN8742_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U) +#define LAN8742_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U) +#define LAN8742_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU) +/** + * @} + */ + +/** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition + * @{ + */ +#define LAN8742_ENCTR_TX_ENABLE ((uint16_t)0x8000U) +#define LAN8742_ENCTR_TX_TIMER ((uint16_t)0x6000U) +#define LAN8742_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U) +#define LAN8742_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U) +#define LAN8742_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U) +#define LAN8742_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U) +#define LAN8742_ENCTR_RX_ENABLE ((uint16_t)0x1000U) +#define LAN8742_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U) +#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U) +#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U) +#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U) +#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U) +#define LAN8742_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U) +#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U) +/** + * @} + */ + +/** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition + * @{ + */ +#define LAN8742_MCSR_EDPWRDOWN ((uint16_t)0x2000U) +#define LAN8742_MCSR_FARLOOPBACK ((uint16_t)0x0200U) +#define LAN8742_MCSR_ALTINT ((uint16_t)0x0040U) +#define LAN8742_MCSR_ENERGYON ((uint16_t)0x0002U) +/** + * @} + */ + +/** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition + * @{ + */ +#define LAN8742_SMR_MODE ((uint16_t)0x00E0U) +#define LAN8742_SMR_PHY_ADDR ((uint16_t)0x001FU) +/** + * @} + */ + +/** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition + * @{ + */ +#define LAN8742_TPDCR_DELAY_IN ((uint16_t)0x8000U) +#define LAN8742_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U) +#define LAN8742_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U) +#define LAN8742_TPDCR_PATTERN_LOW ((uint16_t)0x003FU) +/** + * @} + */ + +/** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition + * @{ + */ +#define LAN8742_TCSR_TDR_ENABLE ((uint16_t)0x8000U) +#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U) +#define LAN8742_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U) +#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U) +#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U) +#define LAN8742_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U) +#define LAN8742_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U) +#define LAN8742_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U) +#define LAN8742_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU) +/** + * @} + */ + +/** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition + * @{ + */ +#define LAN8742_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U) +#define LAN8742_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U) +#define LAN8742_SCSIR_SQE_DISABLE ((uint16_t)0x0800U) +#define LAN8742_SCSIR_XPOLALITY ((uint16_t)0x0010U) +/** + * @} + */ + +/** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition + * @{ + */ +#define LAN8742_CLR_CABLE_LENGTH ((uint16_t)0xF000U) +/** + * @} + */ + +/** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition + * @{ + */ +#define LAN8742_INT_8 ((uint16_t)0x0100U) +#define LAN8742_INT_7 ((uint16_t)0x0080U) +#define LAN8742_INT_6 ((uint16_t)0x0040U) +#define LAN8742_INT_5 ((uint16_t)0x0020U) +#define LAN8742_INT_4 ((uint16_t)0x0010U) +#define LAN8742_INT_3 ((uint16_t)0x0008U) +#define LAN8742_INT_2 ((uint16_t)0x0004U) +#define LAN8742_INT_1 ((uint16_t)0x0002U) +/** + * @} + */ + +/** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition + * @{ + */ +#define LAN8742_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x1000U) +#define LAN8742_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x001CU) +#define LAN8742_PHYSCSR_10BT_HD ((uint16_t)0x0004U) +#define LAN8742_PHYSCSR_10BT_FD ((uint16_t)0x0014U) +#define LAN8742_PHYSCSR_100BTX_HD ((uint16_t)0x0008U) +#define LAN8742_PHYSCSR_100BTX_FD ((uint16_t)0x0018U) +/** + * @} + */ + +/** @defgroup LAN8742_Status LAN8742 Status + * @{ + */ + +#define LAN8742_STATUS_READ_ERROR ((int32_t)-5) +#define LAN8742_STATUS_WRITE_ERROR ((int32_t)-4) +#define LAN8742_STATUS_ADDRESS_ERROR ((int32_t)-3) +#define LAN8742_STATUS_RESET_TIMEOUT ((int32_t)-2) +#define LAN8742_STATUS_ERROR ((int32_t)-1) +#define LAN8742_STATUS_OK ((int32_t) 0) +#define LAN8742_STATUS_LINK_DOWN ((int32_t) 1) +#define LAN8742_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2) +#define LAN8742_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3) +#define LAN8742_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4) +#define LAN8742_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5) +#define LAN8742_STATUS_AUTONEGO_NOTDONE ((int32_t) 6) +/** + * @} + */ + +/** @defgroup LAN8742_IT_Flags LAN8742 IT Flags + * @{ + */ +#define LAN8742_WOL_IT LAN8742_INT_8 +#define LAN8742_ENERGYON_IT LAN8742_INT_7 +#define LAN8742_AUTONEGO_COMPLETE_IT LAN8742_INT_6 +#define LAN8742_REMOTE_FAULT_IT LAN8742_INT_5 +#define LAN8742_LINK_DOWN_IT LAN8742_INT_4 +#define LAN8742_AUTONEGO_LP_ACK_IT LAN8742_INT_3 +#define LAN8742_PARALLEL_DETECTION_FAULT_IT LAN8742_INT_2 +#define LAN8742_AUTONEGO_PAGE_RECEIVED_IT LAN8742_INT_1 +/** + * @} + */ + +/** + * @} + */ + +/* Exported types ------------------------------------------------------------*/ +/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types + * @{ + */ +typedef int32_t (*lan8742_Init_Func)(void); +typedef int32_t (*lan8742_DeInit_Func)(void); +typedef int32_t (*lan8742_ReadReg_Func)(uint32_t, uint32_t, uint32_t *); +typedef int32_t (*lan8742_WriteReg_Func)(uint32_t, uint32_t, uint32_t); +typedef int32_t (*lan8742_GetTick_Func)(void); + +typedef struct { + lan8742_Init_Func Init; + lan8742_DeInit_Func DeInit; + lan8742_WriteReg_Func WriteReg; + lan8742_ReadReg_Func ReadReg; + lan8742_GetTick_Func GetTick; +} lan8742_IOCtx_t; + + +typedef struct { + uint32_t DevAddr; + uint32_t Is_Initialized; + lan8742_IOCtx_t IO; + void *pData; +} lan8742_Object_t; +/** + * @} + */ + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ +/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions + * @{ + */ +int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx); +int32_t LAN8742_Init(lan8742_Object_t *pObj); +int32_t LAN8742_DeInit(lan8742_Object_t *pObj); +int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj); +int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj); +int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj); +int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj); +int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState); +int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj); +int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj); +int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt); +int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt); +int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt); +int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt); +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* __LAN8742_H */ + + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h new file mode 100644 index 0000000..cd943cc --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2017 ARM Limited + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32XX_EMAC_CONFIG_H__ +#define STM32XX_EMAC_CONFIG_H__ + +#define ETH_IP_VERSION_V2 + +#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/connectivity/drivers/emac/TARGET_STM/mbed_lib.json b/connectivity/drivers/emac/TARGET_STM/mbed_lib.json new file mode 100644 index 0000000..5a86535 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/mbed_lib.json @@ -0,0 +1,59 @@ +{ + "name": "stm32-emac", + "config": { + "eth-rxbufnb": 4, + "eth-txbufnb": 4, + "thread-stacksize": { + "help": "Stack size for stm32_emac_thread", + "value": 1024 + }, + "eth-phy-address": { + "help" : "Configures actual PHY address according to pullup/down status of PHYAD pin(s)", + "value" : 0 + }, + "eth-phy-media-interface": { + "help" : "Selects Connection to PHY Chip: ETH_MEDIA_INTERFACE_RMII / ETH_MEDIA_INTERFACE_MII", + "value" : "ETH_MEDIA_INTERFACE_RMII" + }, + "eth-phy-AutoNegotiation": { + "help" : "Selects AutoNegotiation mode : ETH_AUTONEGOTIATION_ENABLE / ETH_AUTONEGOTIATION_DISABLE", + "value" : "ETH_AUTONEGOTIATION_ENABLE" + }, + "eth-phy-DuplexMode": { + "help" : "Selects DuplexMode mode : ETH_MODE_FULLDUPLEX / ETH_MODE_HALFDUPLEX", + "value" : "ETH_MODE_FULLDUPLEX" + }, + "eth-phy-Speed": { + "help" : "Selects Speed mode : ETH_SPEED_100M / ETH_SPEED_10M", + "value" : "ETH_SPEED_100M" + }, + "eth-phy-reset-delay": { + "help" : "Reset process time - Default value: 0.5s as specified in LAN8742A datasheet", + "value" : "500" + }, + "eth-phy-status-register": { + "help" : "PHY register Offset with auto-negotiation result - Default value is LAN8742A PHY Special Control/Status Register", + "value" : "31" + }, + "eth-phy-speed-status": { + "help" : "Speed mask information in eth-phy-status-register", + "value" : "0x0004" + }, + "eth-phy-duplex-status": { + "help" : "Duplex mask information in eth-phy-status-register", + "value" : "0x0010" + } + }, + "target_overrides": { + "NUCLEO_F207ZG": { + "eth-rxbufnb": 2, + "eth-txbufnb": 4 + }, + "STM32H7": { + "eth-txbufnb": 10 + }, + "ARCH_MAX": { + "eth-phy-address": 1 + } + } +} diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp new file mode 100644 index 0000000..7ae8276 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.cpp @@ -0,0 +1,1086 @@ +/* Copyright (c) 2017-2019 ARM Limited + * Copyright (c) 2017-2019 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#if DEVICE_EMAC + +#include + +#include "cmsis_os.h" + +#include "mbed.h" +#include "mbed_interface.h" +#include "mbed_assert.h" +#include "mbed_shared_queues.h" +#include "netsocket/nsapi_types.h" + +#include "stm32xx_emac_config.h" +#include "stm32xx_emac.h" + +#include "mbed-trace/mbed_trace.h" + +#if defined(ETH_IP_VERSION_V2) +#define TRACE_GROUP "STE2" +#else +#define TRACE_GROUP "STE1" +#endif + +/* mbed trace feature is supported */ +/* ex in mbed_app.json */ +/* "mbed-trace.enable": "1" */ + +/* mbed_trace: debug traces (tr_debug) can be disabled here with no change in mbed_app.json */ +// #undef TRACE_LEVEL_DEBUG +// #define TRACE_LEVEL_DEBUG 0 + +#if defined(ETH_IP_VERSION_V2) +#include "lan8742/lan8742.h" +#include "lwip/memp.h" +#include "lwip/api.h" +#endif + +using namespace std::chrono; + +/* \brief Flags for worker thread */ +#define FLAG_RX 1 + +/** \brief Driver thread priority */ +#define THREAD_PRIORITY (osPriorityHigh) + +#define PHY_TASK_PERIOD 200ms + +#define STM_HWADDR_SIZE (6) +#define STM_ETH_MTU_SIZE 1500 +#define STM_ETH_IF_NAME "st" + +#ifndef ETH_IP_VERSION_V2 + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; /* Ethernet Rx DMA Descriptor */ + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; /* Ethernet Tx DMA Descriptor */ + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */ + +#if defined (__ICCARM__) /*!< IAR Compiler */ +#pragma data_alignment=4 +#endif +__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */ + +#else // ETH_IP_VERSION_V2 + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + +#pragma location=0x30040000 +ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ +#pragma location=0x30040100 +ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ +#pragma location=0x30040400 +uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */ + +#elif defined ( __GNUC__ ) /* GCC & ARMC6*/ + +ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ +ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ +uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */ + +#endif + +static lan8742_Object_t LAN8742; + +static int32_t ETH_PHY_IO_Init(void); +static int32_t ETH_PHY_IO_DeInit(void); +static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); +static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); +static int32_t ETH_PHY_IO_GetTick(void); + +static lan8742_IOCtx_t LAN8742_IOCtx = { + ETH_PHY_IO_Init, + ETH_PHY_IO_DeInit, + ETH_PHY_IO_WriteReg, + ETH_PHY_IO_ReadReg, + ETH_PHY_IO_GetTick +}; + +static ETH_TxPacketConfig TxConfig; + +#endif // ETH_IP_VERSION_V2 + +__weak uint8_t mbed_otp_mac_address(char *mac); +void mbed_default_mac_address(char *mac); + +#ifdef __cplusplus +extern "C" { +#endif + +void _eth_config_mac(ETH_HandleTypeDef *heth); +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); +void ETH_IRQHandler(void); + +#ifdef __cplusplus +} +#endif + +#ifdef ETH_IP_VERSION_V2 +bool _phy_init() +{ + /* Set PHY IO functions */ + LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx); + + /* Initialize the LAN8742 ETH PHY */ + return LAN8742_Init(&LAN8742) == LAN8742_STATUS_OK; +} + +int32_t _phy_get_state() +{ + return LAN8742_GetLinkState(&LAN8742); +} + +bool _phy_get_duplex_and_speed(int32_t phy_state, uint32_t *duplex, uint32_t *speed) +{ + switch (phy_state) { + case LAN8742_STATUS_100MBITS_FULLDUPLEX: + *duplex = ETH_FULLDUPLEX_MODE; + *speed = ETH_SPEED_100M; + break; + case LAN8742_STATUS_100MBITS_HALFDUPLEX: + *duplex = ETH_HALFDUPLEX_MODE; + *speed = ETH_SPEED_100M; + break; + case LAN8742_STATUS_10MBITS_FULLDUPLEX: + *duplex = ETH_FULLDUPLEX_MODE; + *speed = ETH_SPEED_10M; + break; + case LAN8742_STATUS_10MBITS_HALFDUPLEX: + *duplex = ETH_HALFDUPLEX_MODE; + *speed = ETH_SPEED_10M; + break; + default: + return false; + } + + return true; +} + +bool _phy_is_up(int32_t phy_state) +{ + return phy_state > LAN8742_STATUS_LINK_DOWN; +} + +static void MPU_Config(void) +{ + MPU_Region_InitTypeDef MPU_InitStruct; + + /* Disable the MPU */ + HAL_MPU_Disable(); + + /* Configure the MPU attributes as Device not cacheable + for ETH DMA descriptors */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.BaseAddress = 0x30040000; + MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + /* Configure the MPU attributes as Cacheable write through + for LwIP RAM heap which contains the Tx buffers */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.BaseAddress = 0x30044000; + MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER1; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.SubRegionDisable = 0x00; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + + /* Enable the MPU */ + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); +} + +#endif + + + +/** + * Ethernet Rx Transfer completed callback + * + * @param heth: ETH handle + * @retval None + */ +void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + if (emac.thread) { + osThreadFlagsSet(emac.thread, FLAG_RX); + } +} + +/** + * Ethernet IRQ Handler + * + * @param None + * @retval None + */ +void ETH_IRQHandler(void) +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + HAL_ETH_IRQHandler(&emac.EthHandle); +} + +STM32_EMAC::STM32_EMAC() + : thread(0) +#ifdef ETH_IP_VERSION_V2 + , phy_status(0) +#endif +{ +} + +static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) +{ + osThreadAttr_t attr = {0}; + attr.name = threadName; + attr.stack_mem = malloc(stacksize); + attr.cb_mem = thread_cb; + attr.stack_size = stacksize; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = priority; + return osThreadNew(thread, arg, &attr); +} + +/** + * In this function, the hardware should be initialized. + */ +bool STM32_EMAC::low_level_init_successful() +#ifndef ETH_IP_VERSION_V2 +{ + uint32_t PHY_ID; + + /* Init ETH */ + uint8_t MACAddr[6]; + EthHandle.Instance = ETH; + EthHandle.Init.AutoNegotiation = MBED_CONF_STM32_EMAC_ETH_PHY_AUTONEGOTIATION; + EthHandle.Init.Speed = MBED_CONF_STM32_EMAC_ETH_PHY_SPEED; + EthHandle.Init.DuplexMode = MBED_CONF_STM32_EMAC_ETH_PHY_DUPLEXMODE; + EthHandle.Init.PhyAddress = MBED_CONF_STM32_EMAC_ETH_PHY_ADDRESS; +#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) + MACAddr[0] = MBED_MAC_ADDR_0; + MACAddr[1] = MBED_MAC_ADDR_1; + MACAddr[2] = MBED_MAC_ADDR_2; + MACAddr[3] = MBED_MAC_ADDR_3; + MACAddr[4] = MBED_MAC_ADDR_4; + MACAddr[5] = MBED_MAC_ADDR_5; +#else + mbed_mac_address((char *)MACAddr); +#endif + EthHandle.Init.MACAddr = &MACAddr[0]; + EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; + EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; + EthHandle.Init.MediaInterface = MBED_CONF_STM32_EMAC_ETH_PHY_MEDIA_INTERFACE; + tr_info("PHY Addr %u AutoNegotiation %u", EthHandle.Init.PhyAddress, EthHandle.Init.AutoNegotiation); + tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]); + tr_info("ETH buffers : %u Rx %u Tx", ETH_RXBUFNB, ETH_TXBUFNB); + + if (HAL_ETH_Init(&EthHandle) != HAL_OK) { + tr_error("HAL_ETH_Init issue"); + /* HAL_ETH_Init returns TIMEOUT when Ethernet cable is not plugged */; + } + + uint32_t TempRegisterValue; + if (HAL_ETH_ReadPHYRegister(&EthHandle, 2, &TempRegisterValue) != HAL_OK) { + tr_error("HAL_ETH_ReadPHYRegister 2 issue"); + } + PHY_ID = (TempRegisterValue << 16); + if (HAL_ETH_ReadPHYRegister(&EthHandle, 3, &TempRegisterValue) != HAL_OK) { + tr_error("HAL_ETH_ReadPHYRegister 3 issue"); + } + PHY_ID |= (TempRegisterValue & 0XFFF0); + tr_info("PHY ID %#X", PHY_ID); + + /* Initialize Tx Descriptors list: Chain Mode */ + if (HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB) != HAL_OK) { + tr_error("HAL_ETH_DMATxDescListInit issue"); + return false; + } + + /* Initialize Rx Descriptors list: Chain Mode */ + if (HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB) != HAL_OK) { + tr_error("HAL_ETH_DMARxDescListInit issue"); + return false; + } + + /* Configure MAC */ + _eth_config_mac(&EthHandle); + + /* Enable MAC and DMA transmission and reception */ + if (HAL_ETH_Start(&EthHandle) != HAL_OK) { + tr_error("HAL_ETH_Start issue"); + return false; + } + + tr_info("low_level_init_successful"); + return true; +} +#else // ETH_IP_VERSION_V2 +{ + uint32_t idx; + + MPU_Config(); + + /* Init ETH */ + uint8_t MACAddr[6]; + EthHandle.Instance = ETH; +#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) + MACAddr[0] = MBED_MAC_ADDR_0; + MACAddr[1] = MBED_MAC_ADDR_1; + MACAddr[2] = MBED_MAC_ADDR_2; + MACAddr[3] = MBED_MAC_ADDR_3; + MACAddr[4] = MBED_MAC_ADDR_4; + MACAddr[5] = MBED_MAC_ADDR_5; +#else + mbed_mac_address((char *)MACAddr); +#endif + EthHandle.Init.MACAddr = &MACAddr[0]; + EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; + EthHandle.Init.RxDesc = DMARxDscrTab; + EthHandle.Init.TxDesc = DMATxDscrTab; + EthHandle.Init.RxBuffLen = 1524; + + tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]); + tr_info("ETH buffers : %u Rx %u Tx", ETH_RX_DESC_CNT, ETH_TX_DESC_CNT); + + if (HAL_ETH_Init(&EthHandle) != HAL_OK) { + return false; + } + + memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig)); + TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; + TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; + TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; + + for (idx = 0; idx < ETH_RX_DESC_CNT; idx++) { + HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL); + } + + tr_info("low_level_init_successful"); + return _phy_init(); +} +#endif // ETH_IP_VERSION_V2 + +/** + * This function should do the actual transmission of the packet. The packet is + * contained in the memory buffer chain that is passed to the function. + * + * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) + * @return true if the packet could be sent + * false value if the packet couldn't be sent + * + * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to + * strange results. You might consider waiting for space in the DMA queue + * to become availale since the stack doesn't retry to send a packet + * dropped because of memory failure (except for the TCP timers). + */ +bool STM32_EMAC::link_out(emac_mem_buf_t *buf) +#ifndef ETH_IP_VERSION_V2 +{ + bool success = true; + emac_mem_buf_t *q; + uint8_t *buffer = reinterpret_cast(EthHandle.TxDesc->Buffer1Addr); + __IO ETH_DMADescTypeDef *DmaTxDesc; + uint32_t framelength = 0; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + uint32_t payloadoffset = 0; + DmaTxDesc = EthHandle.TxDesc; + + /* Get exclusive access */ + TXLockMutex.lock(); + + /* copy frame from pbufs to driver buffers */ + for (q = buf; q != NULL; q = memory_manager->get_next(q)) { + /* Is this buffer available? If not, goto error */ + if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { + success = false; + goto error; + } + + /* Get bytes in current lwIP buffer */ + byteslefttocopy = memory_manager->get_len(q); + payloadoffset = 0; + + /* Check if the length of data to copy is bigger than Tx buffer size*/ + while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) { + /* Copy data to Tx buffer*/ + memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, (ETH_TX_BUF_SIZE - bufferoffset)); + + /* Point to next descriptor */ + DmaTxDesc = reinterpret_cast(DmaTxDesc->Buffer2NextDescAddr); + + /* Check if the buffer is available */ + if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { + success = false; + goto error; + } + + buffer = reinterpret_cast(DmaTxDesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); + framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + + /* Copy the remaining bytes */ + memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + framelength = framelength + byteslefttocopy; + } + + /* Prepare transmit descriptors to give to DMA */ + if (HAL_ETH_TransmitFrame(&EthHandle, framelength) != HAL_OK) { + tr_error("HAL_ETH_TransmitFrame issue"); + success = false; + } + +error: + + /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) { + /* Clear TUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_TUS; + + /* Resume DMA transmission*/ + EthHandle.Instance->DMATPDR = 0; + } + + memory_manager->free(buf); + + /* Restore access */ + TXLockMutex.unlock(); + + return success; +} +#else // ETH_IP_VERSION_V2 +{ + bool success = false; + uint32_t i = 0; + uint32_t frameLength = 0; + struct pbuf *q; + ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; + HAL_StatusTypeDef status; + struct pbuf *p = NULL; + p = (struct pbuf *)buf; + /* Get exclusive access */ + TXLockMutex.lock(); + + memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef)); + + /* copy frame from pbufs to driver buffers */ + for (q = p; q != NULL; q = q->next) { + if (i >= ETH_TX_DESC_CNT) { + tr_error("Error : ETH_TX_DESC_CNT not sufficient"); + goto error; + } + + Txbuffer[i].buffer = (uint8_t *)q->payload; + Txbuffer[i].len = q->len; + frameLength += q->len; + + if (i > 0) { + Txbuffer[i - 1].next = &Txbuffer[i]; + } + + if (q->next == NULL) { + Txbuffer[i].next = NULL; + } + + i++; + } + + TxConfig.Length = frameLength; + TxConfig.TxBuffer = Txbuffer; + + status = HAL_ETH_Transmit(&EthHandle, &TxConfig, 50); + if (status == HAL_OK) { + success = 1; + } else { + tr_error("Error returned by HAL_ETH_Transmit (%d)", status); + success = 0; + } + +error: + + if (p->ref > 1) { + pbuf_free(p); + } + + /* Restore access */ + TXLockMutex.unlock(); + + return success; +} +#endif // ETH_IP_VERSION_V2 + +/** + * Should allocate a contiguous memory buffer and transfer the bytes of the incoming + * packet to the buffer. + * + * @param buf If a frame was received and the memory buffer allocation was successful, a memory + * buffer filled with the received packet (including MAC header) + * @return negative value when no more frames, + * zero when frame is received + */ +int STM32_EMAC::low_level_input(emac_mem_buf_t **buf) +#ifndef ETH_IP_VERSION_V2 +{ + uint32_t len = 0; + uint8_t *buffer; + __IO ETH_DMADescTypeDef *dmarxdesc; + uint32_t bufferoffset = 0; + uint32_t byteslefttocopy = 0; + emac_mem_buf_t *q; + uint32_t payloadoffset = 0; + + /* get received frame */ + if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) { + tr_debug("low_level_input no frame"); + return -1; + } + + /* Obtain the size of the packet and put it into the "len" variable. */ + len = EthHandle.RxFrameInfos.length; + buffer = reinterpret_cast(EthHandle.RxFrameInfos.buffer); + byteslefttocopy = len; + + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + + if (len > 0 && len <= ETH_RX_BUF_SIZE) { + tr_debug("low_level_input len %u", len); + /* Allocate a memory buffer chain from buffer pool */ + *buf = memory_manager->alloc_pool(len, 0); + } + + if (*buf != NULL) { + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + bufferoffset = 0; + for (q = *buf; q != NULL; q = memory_manager->get_next(q)) { + byteslefttocopy = memory_manager->get_len(q); + payloadoffset = 0; + + /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ + while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) { + /* Copy data to pbuf */ + memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, ETH_RX_BUF_SIZE - bufferoffset); + + /* Point to next descriptor */ + dmarxdesc = reinterpret_cast(dmarxdesc->Buffer2NextDescAddr); + buffer = reinterpret_cast(dmarxdesc->Buffer1Addr); + + byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); + payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); + bufferoffset = 0; + } + /* Copy remaining data in pbuf */ + memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, byteslefttocopy); + bufferoffset = bufferoffset + byteslefttocopy; + } + } + + /* Release descriptors to DMA */ + /* Point to first descriptor */ + dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; + /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ + for (uint32_t i = 0; i < EthHandle.RxFrameInfos.SegCount; i++) { + dmarxdesc->Status |= ETH_DMARXDESC_OWN; + dmarxdesc = reinterpret_cast(dmarxdesc->Buffer2NextDescAddr); + } + + /* Clear Segment_Count */ + EthHandle.RxFrameInfos.SegCount = 0; + + /* When Rx Buffer unavailable flag is set: clear it and resume reception */ + if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) { + /* Clear RBUS ETHERNET DMA flag */ + EthHandle.Instance->DMASR = ETH_DMASR_RBUS; + /* Resume DMA reception */ + EthHandle.Instance->DMARPDR = 0; + } + return 0; +} +#else // ETH_IP_VERSION_V2 +{ + ETH_BufferTypeDef RxBuff; + uint32_t frameLength = 0; + + if (HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK) { + if (HAL_ETH_GetRxDataLength(&EthHandle, &frameLength) != HAL_OK) { + tr_error("Error: returned by HAL_ETH_GetRxDataLength"); + return -1; + } + + /* Build Rx descriptor to be ready for next data reception */ + HAL_ETH_BuildRxDescriptors(&EthHandle); + + /* Invalidate data cache for ETH Rx Buffers */ + SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, frameLength); + + *buf = pbuf_alloc(PBUF_RAW, frameLength, PBUF_POOL); + if (*buf) { + pbuf_take((struct pbuf *)*buf, RxBuff.buffer, frameLength); + } + } else { + return -1; + } + + return 0; +} +#endif // ETH_IP_VERSION_V2 + +/** \brief Attempt to read a packet from the EMAC interface. + * + */ +void STM32_EMAC::packet_rx() +{ + /* move received packet into a new buf */ + while (1) { + emac_mem_buf_t *p = NULL; + RXLockMutex.lock(); + if (low_level_input(&p) < 0) { + RXLockMutex.unlock(); + break; + } + if (p) { + emac_link_input_cb(p); + } + RXLockMutex.unlock(); + } +} + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void STM32_EMAC::thread_function(void *pvParameters) +{ + static struct STM32_EMAC *stm32_enet = static_cast(pvParameters); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX, osFlagsWaitAny, osWaitForever); + + if (flags & FLAG_RX) { + stm32_enet->packet_rx(); + } + } +} + +/** + * This task checks phy link status and updates net status + */ +void STM32_EMAC::phy_task() +#ifndef ETH_IP_VERSION_V2 +{ + uint32_t status; + + if (HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &status) == HAL_OK) { + if ((emac_link_state_cb) && (status != 0xFFFF)) { + if ((status & PHY_LINKED_STATUS) && !(phy_status & PHY_LINKED_STATUS)) { + tr_info("emac_link_state_cb set to true"); + emac_link_state_cb(true); + } else if (!(status & PHY_LINKED_STATUS) && (phy_status & PHY_LINKED_STATUS)) { + tr_info("emac_link_state_cb set to false"); + emac_link_state_cb(false); + } + } + phy_status = status; + } else { + tr_error("HAL_ETH_ReadPHYRegister issue"); + } + +} +#else // ETH_IP_VERSION_V2 +{ + const int32_t status = _phy_get_state(); + const int32_t old_status = (int32_t)phy_status; + const bool is_up = _phy_is_up(status); + const bool was_up = _phy_is_up(old_status); + + if (is_up && !was_up) { + uint32_t duplex, speed; + ETH_MACConfigTypeDef MACConf; + + if (!_phy_get_duplex_and_speed(status, &speed, &duplex)) { + // Default + duplex = ETH_FULLDUPLEX_MODE; + speed = ETH_SPEED_10M; + } + + /* Get MAC Config MAC */ + HAL_ETH_GetMACConfig(&EthHandle, &MACConf); + MACConf.DuplexMode = duplex; + MACConf.Speed = speed; + HAL_ETH_SetMACConfig(&EthHandle, &MACConf); + HAL_ETH_Start_IT(&EthHandle); + } else if (was_up && !is_up) { + // Stop ETH + disable_interrupts(); + HAL_ETH_Stop(&EthHandle); + enable_interrupts(); + } + + if (emac_link_state_cb) { + if (is_up && !was_up) { + emac_link_state_cb(true); + tr_info("emac_link_state_cb set to true"); + } else if (!is_up && was_up) { + emac_link_state_cb(false); + tr_info("emac_link_state_cb set to false"); + } + } + + phy_status = (uint32_t)status; +} +#endif // ETH_IP_VERSION_V2 + +#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ + || defined (STM32F779xx) +/** + * workaround for the ETH RMII bug in STM32F76x and STM32F77x revA + * + * \param[in] netif the lwip network interface structure + */ + +/** \brief Worker thread. + * + * Woken by thread flags to receive packets or clean up transmit + * + * \param[in] pvParameters pointer to the interface data + */ +void STM32_EMAC::rmii_watchdog_thread_function(void *pvParameters) +{ + struct STM32_EMAC *stm32_enet = static_cast(pvParameters); + + while (1) { + /* some good packets are received */ + if (stm32_enet->EthHandle.Instance->MMCRGUFCR > 0) { + /* RMII Init is OK - would need service to terminate or suspend + * the thread */ + while (1) { + /* don't do anything anymore */ + osDelay(0xFFFFFFFF); + } + } else if (stm32_enet->EthHandle.Instance->MMCRFCECR > 10) { + /* ETH received too many packets with CRC errors, resetting RMII */ + SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; + SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; + stm32_enet->EthHandle.Instance->MMCCR |= ETH_MMCCR_CR; + } else { + osDelay(100); + } + } +} +#endif + +void STM32_EMAC::enable_interrupts(void) +{ + HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); + HAL_NVIC_EnableIRQ(ETH_IRQn); +} + +void STM32_EMAC::disable_interrupts(void) +{ + NVIC_DisableIRQ(ETH_IRQn); +} + +/** This returns a unique 6-byte MAC address, based on the device UID +* This function overrides hal/common/mbed_interface.c function +* @param mac A 6-byte array to write the MAC address +*/ + +void mbed_mac_address(char *mac) +{ + if (mbed_otp_mac_address(mac)) { + return; + } else { + mbed_default_mac_address(mac); + } + return; +} + +__weak uint8_t mbed_otp_mac_address(char *mac) +{ + return 0; +} + +void mbed_default_mac_address(char *mac) +{ + unsigned char ST_mac_addr[3] = {0x00, 0x80, 0xe1}; // default STMicro mac address + + // Read unic id +#if defined (TARGET_STM32F2) + uint32_t word0 = *(uint32_t *)0x1FFF7A10; +#elif defined (TARGET_STM32F4) + uint32_t word0 = *(uint32_t *)0x1FFF7A10; +#elif defined (TARGET_STM32F7) + uint32_t word0 = *(uint32_t *)0x1FF0F420; +#elif defined (TARGET_STM32H7) + uint32_t word0 = *(uint32_t *)0x1FF1E800; +#else +#error MAC address can not be derived from target unique Id +#endif + + mac[0] = ST_mac_addr[0]; + mac[1] = ST_mac_addr[1]; + mac[2] = ST_mac_addr[2]; + mac[3] = (word0 & 0x00ff0000) >> 16; + mac[4] = (word0 & 0x0000ff00) >> 8; + mac[5] = (word0 & 0x000000ff); + + return; +} + +bool STM32_EMAC::power_up() +{ + tr_info("power_up"); + + sleep_manager_lock_deep_sleep(); + + /* Initialize the hardware */ + if (!low_level_init_successful()) { + return false; + } + + /* Worker thread */ +#if MBED_CONF_MBED_TRACE_ENABLE + thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, MBED_CONF_STM32_EMAC_THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb); +#else + thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, MBED_CONF_STM32_EMAC_THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); +#endif + + + phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &STM32_EMAC::phy_task)); + +#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ + || defined (STM32F779xx) + rmii_watchdog_thread = create_new_thread("stm32_rmii_watchdog", &STM32_EMAC::rmii_watchdog_thread_function, this, 128, THREAD_PRIORITY, &rmii_watchdog_thread_cb); +#endif + + /* Allow the PHY task to detect the initial link state and set up the proper flags */ + osDelay(10); + + enable_interrupts(); + + return true; +} + +uint32_t STM32_EMAC::get_mtu_size() const +{ + return STM_ETH_MTU_SIZE; +} + +uint32_t STM32_EMAC::get_align_preference() const +{ + return 0; +} + +void STM32_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, STM_ETH_IF_NAME, (size < sizeof(STM_ETH_IF_NAME)) ? size : sizeof(STM_ETH_IF_NAME)); +} + +uint8_t STM32_EMAC::get_hwaddr_size() const +{ + return STM_HWADDR_SIZE; +} + +bool STM32_EMAC::get_hwaddr(uint8_t *addr) const +{ + mbed_mac_address((char *)addr); + return true; +} + +void STM32_EMAC::set_hwaddr(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void STM32_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void STM32_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void STM32_EMAC::add_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void STM32_EMAC::remove_multicast_group(const uint8_t *addr) +{ + /* No-op at this stage */ +} + +void STM32_EMAC::set_all_multicast(bool all) +{ + /* No-op at this stage */ +} + +void STM32_EMAC::power_down() +{ + tr_info("power_down"); + + /* No-op at this stage */ + sleep_manager_unlock_deep_sleep(); +} + +void STM32_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +STM32_EMAC &STM32_EMAC::get_instance() +{ + static STM32_EMAC emac; + return emac; +} + +// Weak so a module can override +MBED_WEAK EMAC &EMAC::get_default_instance() +{ + return STM32_EMAC::get_instance(); +} + +#if defined(ETH_IP_VERSION_V2) +/******************************************************************************* + PHI IO Functions +*******************************************************************************/ + +/** + * @brief Initializes the MDIO interface GPIO and clocks. + * @param None + * @retval 0 if OK, -1 if ERROR + */ +static int32_t ETH_PHY_IO_Init(void) +{ + /* We assume that MDIO GPIO configuration is already done + in the ETH_MspInit() else it should be done here + */ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + + /* Configure the MDIO Clock */ + HAL_ETH_SetMDIOClockRange(&emac.EthHandle); + + return 0; +} + +/** + * @brief De-Initializes the MDIO interface . + * @param None + * @retval 0 if OK, -1 if ERROR + */ +static int32_t ETH_PHY_IO_DeInit(void) +{ + return 0; +} + +/** + * @brief Read a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param pRegVal: pointer to hold the register value + * @retval 0 if OK -1 if Error + */ +static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + if (HAL_ETH_ReadPHYRegister(&emac.EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK) { + return -1; + } + + return 0; +} + +/** + * @brief Write a value to a PHY register through the MDIO interface. + * @param DevAddr: PHY port address + * @param RegAddr: PHY register address + * @param RegVal: Value to be written + * @retval 0 if OK -1 if Error + */ +static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) +{ + STM32_EMAC &emac = STM32_EMAC::get_instance(); + if (HAL_ETH_WritePHYRegister(&emac.EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK) { + return -1; + } + + return 0; +} + +/** + * @brief Get the time in millisecons used for internal PHY driver process. + * @retval Time value + */ +static int32_t ETH_PHY_IO_GetTick(void) +{ + return HAL_GetTick(); +} + +/** + * Ethernet DMA transfer error callbacks + */ +void HAL_ETH_DMAErrorCallback(ETH_HandleTypeDef *heth) +{ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \ + "Error from ethernet HAL (HAL_ETH_DMAErrorCallback)\n"); +} + +/** + * Ethernet MAC transfer error callbacks + */ +void HAL_ETH_MACErrorCallback(ETH_HandleTypeDef *heth) +{ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \ + "Error from ethernet HAL (HAL_ETH_MACErrorCallback)\n"); +} +#endif // ETH_IP_VERSION_V2 + +#endif /* DEVICE_EMAC */ diff --git a/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h new file mode 100644 index 0000000..cfa6752 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_STM/stm32xx_emac.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2017 ARM Limited + * Copyright (c) 2017 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STM32_EMAC_H_ +#define STM32_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Mutex.h" + +class STM32_EMAC : public EMAC { +public: + STM32_EMAC(); + + static STM32_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not + * align link out memory buffer chains using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own HW + * address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is provided + * the stack would normally use that, but it could be overridden, eg for test + * purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + // Called from driver functions + ETH_HandleTypeDef EthHandle; + osThreadId_t thread; /**< Processing thread */ + +private: + bool low_level_init_successful(); + void packet_rx(); + int low_level_input(emac_mem_buf_t **buf); + static void thread_function(void *pvParameters); + static void rmii_watchdog_thread_function(void *pvParameters); + void phy_task(); + void enable_interrupts(); + void disable_interrupts(); + + mbed_rtos_storage_thread_t thread_cb; +#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ + || defined (STM32F779xx) + mbed_rtos_storage_thread_t rmii_watchdog_thread_cb; + osThreadId_t rmii_watchdog_thread; /**< Watchdog processing thread */ +#endif + rtos::Mutex TXLockMutex;/**< TX critical section mutex */ + rtos::Mutex RXLockMutex;/**< RX critical section mutex */ + emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ + emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ + EMACMemoryManager *memory_manager; /**< Memory manager */ + + uint32_t phy_status; + int phy_task_handle; /**< Handle for phy task event */ +}; + +#endif /* STM32_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/mbed_lib.json b/connectivity/drivers/emac/TARGET_Silicon_Labs/mbed_lib.json new file mode 100644 index 0000000..a7d2bf6 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/mbed_lib.json @@ -0,0 +1,34 @@ +{ + "name": "sl-eth", + "config": { + "rmii-location": { + "help": "Location number to use for the RMII pins, see chip datasheet", + "value": null + }, + "mdio-location": { + "help": "Location number to use for the MDIO pins, see chip datasheet", + "value": null + }, + "refclk-location": { + "help": "Location number to use for the REFCLK output from CMU (CLKOUTSEL2), see chip datasheet", + "value": null + }, + "phy-enable-pin": { + "help": "Pin attached to the PHY enable line", + "value": null + }, + "phy-power-pin": { + "help": "Pin used to switch on power to the PHY. If not defined, we assume the PHY is always powered.", + "value": null + } + }, + "target_overrides": { + "EFM32GG11_STK3701": { + "rmii-location": 1, + "mdio-location": 1, + "refclk-location": 5, + "phy-enable-pin": "PH7", + "phy-power-pin": "PI10" + } + } +} diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.cpp b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.cpp new file mode 100644 index 0000000..14c2115 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.cpp @@ -0,0 +1,711 @@ +/***************************************************************************//** + * @file sl_emac.cpp + ******************************************************************************* + * @section License + * (C) Copyright 2018 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#include "device.h" + +#if defined(ETH_PRESENT) +#include "sl_emac_config.h" +#include "sl_emac.h" +#include "sl_eth_hw.h" +#include "sl_eth_phy.h" +#include "mbed_power_mgmt.h" + +#include + +#include "mbed-trace/mbed_trace.h" +#define TRACE_GROUP "SEth" + +#define FLAG_TX 1 +#define FLAG_RX 2 +#define FLAG_POLL 4 + +// ----------------------------------------------------------------------------- +// Setup +// ----------------------------------------------------------------------------- +bool SL_EMAC::power_up() +{ + // If the worker thread doesn't exist, launch it + if(thread == 0) { + /* Worker thread */ + osThreadAttr_t attr = {0}; + attr.name = "sl_emac_thread"; + attr.stack_mem = malloc(SL_ETH_THREAD_STACKSIZE); + attr.cb_mem = &thread_cb; + attr.stack_size = SL_ETH_THREAD_STACKSIZE; + attr.cb_size = sizeof(mbed_rtos_storage_thread_t); + attr.priority = SL_ETH_THREAD_PRIORITY; + thread = osThreadNew(&this->eth_thread, this, &attr); + } + + // Can't turn off HF clock as long as Ethernet is active + sleep_manager_lock_deep_sleep(); + + // Bring up data structures + data_init(); + + // Bring up clocks + sl_eth_hw_init(); + + // Point to RX queue + ETH->RXQPTR = (uint32_t)rx_bds; + ETH->DMACFG = (ETH->DMACFG & ~_ETH_DMACFG_RXBUFSIZE_MASK) + | ((SL_ETH_RX_BUF_SIZE/64) << _ETH_DMACFG_RXBUFSIZE_SHIFT); + + // Set up MAC address + uint8_t addr[6]; + get_hwaddr(addr); + set_hwaddr(addr); + + ETH->IFCR |= _ETH_IFCR_MASK; + ETH->RXSTATUS = 0xFFFFFFFF; + ETH->TXSTATUS = 0xFFFFFFFF; + ETH->IENS = ETH_IENS_RXCMPLT | + ETH_IENS_RXUSEDBITREAD | + ETH_IENS_TXCMPLT | + ETH_IENS_TXUNDERRUN | + ETH_IENS_RTRYLMTORLATECOL | + ETH_IENS_TXUSEDBITREAD | + ETH_IENS_AMBAERR | + ETH_IENS_MNGMNTDONE; + + ETH->NETWORKCFG |= ETH_NETWORKCFG_FCSREMOVE | + ETH_NETWORKCFG_UNICASTHASHEN | + ETH_NETWORKCFG_MULTICASTHASHEN | + ETH_NETWORKCFG_RXCHKSUMOFFLOADEN; + + ETH->NETWORKCFG |= ETH_NETWORKCFG_FULLDUPLEX | + ETH_NETWORKCFG_SPEED; + + ETH->DMACFG |= _ETH_DMACFG_AMBABRSTLEN_MASK | + ETH_DMACFG_FRCDISCARDONERR | + ETH_DMACFG_TXPBUFTCPEN; + + ETH->DMACFG &= ~ETH_DMACFG_HDRDATASPLITEN; + + ETH->NETWORKCTRL |= ETH_NETWORKCTRL_ENBTX | + ETH_NETWORKCTRL_ENBRX | + ETH_NETWORKCTRL_MANPORTEN; + + phy_init(); + + NVIC_EnableIRQ(ETH_IRQn); + + up = true; + + tr_debug("Link booted"); + + osThreadFlagsSet(thread, FLAG_POLL); + + return true; +} + +void SL_EMAC::power_down() +{ + up = false; + + tr_debug("Link coming down, waiting for TX to be done."); + + tx_sem.acquire(); + + NVIC_DisableIRQ(ETH_IRQn); + + sl_eth_hw_deinit(); + + data_deinit(); + + /* link is down */ + if(connected && emac_link_state_cb) { + emac_link_state_cb(false); + } + connected = false; + + tr_debug("Link down"); + + // Ethernet went down, HF clock is no longer required here + sleep_manager_unlock_deep_sleep(); +} + +void SL_EMAC::data_init(void) +{ + size_t i; + + /* Allocate a full-frame buffer for each RX BD and set up said BD */ + for(i = 0; i < SL_ETH_NUM_RX_BD; i++) { + rx_bufs[i] = memory_manager->alloc_heap(SL_ETH_RX_BUF_SIZE, SL_ETH_ALIGN); + rx_bds[i].addr = ((uint32_t)memory_manager->get_ptr(rx_bufs[i])) & ~0x3; + if(i == SL_ETH_NUM_RX_BD-1) { + rx_bds[i].addr |= 0x2; + } + rx_bds[i].status = 0; + } + + /* Set up TX BDs */ + tx_buf = (emac_mem_buf_t*)NULL; + for(i = 0; i < SL_ETH_NUM_TX_BD; i++) { + tx_bds[i].addr = 0; + tx_bds[i].status = 0; + if(i == SL_ETH_NUM_TX_BD-1) { + tx_bds[i].status |= (0x1 << 30); + } + } + + /* Start RX reception at index 0 */ + rx_idx = 0; +} + +void SL_EMAC::data_deinit(void) +{ + for(size_t i = 0; i < SL_ETH_NUM_RX_BD; i++) { + memory_manager->free(rx_bufs[i]); + } +} + +// ----------------------------------------------------------------------------- +// IRQ & IRQ de-escalation logic +// ----------------------------------------------------------------------------- +/* IRQ handler for ethernet interrupts */ +void ETH_IRQHandler(void) +{ + uint32_t int_clr = 0; + uint32_t int_status = ETH->IFCR; + uint32_t txdone_mask = ETH_IFCR_TXCMPLT | + ETH_IFCR_TXUNDERRUN | + ETH_IFCR_RTRYLMTORLATECOL | + ETH_IFCR_TXUSEDBITREAD | + ETH_IFCR_AMBAERR; + uint32_t rxdone_mask = ETH_IFCR_RXCMPLT | + ETH_IFCR_RXUSEDBITREAD; + + + SL_EMAC &emac = SL_EMAC::get_instance(); + + if(int_status & rxdone_mask) { + if (emac.thread) { + osThreadFlagsSet(emac.thread, FLAG_RX); + } + int_clr |= rxdone_mask; + } + + if(int_status & txdone_mask) { + if (emac.thread) { + osThreadFlagsSet(emac.thread, FLAG_TX); + } + int_clr |= txdone_mask; + } + + int_clr |= ETH_IFCR_MNGMNTDONE; + ETH->IFCR = int_clr; +} + +void SL_EMAC::eth_thread(void* instance) +{ + struct SL_EMAC *emac = static_cast(instance); + + for (;;) { + uint32_t flags = osThreadFlagsWait(FLAG_RX|FLAG_TX|FLAG_POLL, osFlagsWaitAny, SL_ETH_LINK_POLL_PERIOD_MS); + if ((flags == osFlagsErrorTimeout) && emac->up) { + // Rather than calling strictly every period, we call when idle + // for that period - hopefully good enough. We run this task + // from lwIP's thread rather than our RX/TX thread, as PHY reads can + // be slow, and we don't want them to interfere with data pumping. + // This is analogous to the way the PHY polling works in the Nanostack + // version of the driver + emac->link_state_poll(); + continue; + } + + if((flags & FLAG_POLL)) { + emac->link_state_poll(); + continue; + } + + MBED_ASSERT((flags & osFlagsError) == 0); + + /* Packet received */ + if ((flags & FLAG_RX) && emac->up) { + /* Find packets in the RX BD chain which have been fully received. Feed the + * corresponding buffer upstream, and attach a new buffer to the BD. */ + while(emac->rx_bds[emac->rx_idx].addr & 0x1) { + /* DMA has relinquished control over this packet */ + emac_mem_buf_t* buf = emac->rx_bufs[emac->rx_idx]; + emac->memory_manager->set_len(buf, emac->rx_bds[emac->rx_idx].status & 0x1FFF); + + tr_debug("Received packet of size %d", emac->memory_manager->get_len(buf)); + /* Attempt to queue new buffer */ + emac_mem_buf_t* temp_rxbuf = emac->memory_manager->alloc_heap(SL_ETH_RX_BUF_SIZE, 4); + if (NULL == temp_rxbuf) { + /* out of memory, drop packet */ + tr_warn("Packet index %d dropped for OOM", + emac->rx_idx); + emac->rx_bds[emac->rx_idx].addr &= ~0x1; + } else { + emac->rx_bufs[emac->rx_idx] = temp_rxbuf; + + emac->rx_bds[emac->rx_idx].status = 0; + if(emac->rx_bds[emac->rx_idx].addr & 0x2) { + emac->rx_bds[emac->rx_idx].addr = (uint32_t)emac->memory_manager->get_ptr(temp_rxbuf) | 0x2; + } else { + emac->rx_bds[emac->rx_idx].addr = (uint32_t)emac->memory_manager->get_ptr(temp_rxbuf); + } + + /* pass all packets to ethernet_input, which decides what packets it supports */ + if(emac->emac_link_input_cb) { + emac->emac_link_input_cb(buf); + } + } + emac->rx_idx = (emac->rx_idx + 1) % SL_ETH_NUM_RX_BD; + } + } + + /* Packet transmission done */ + if (flags & FLAG_TX) { + /* Free the buffer */ + if(emac->tx_buf != NULL) { + emac->memory_manager->free(emac->tx_buf); + emac->tx_buf = NULL; + } + + /* Signal TX thread(s) we're ready to start TX'ing */ + emac->tx_sem.release(); + } + } +} + +// ----------------------------------------------------------------------------- +// PHY manipulation +// ----------------------------------------------------------------------------- +void SL_EMAC::phy_init(void) +{ + uint8_t phy_addr = 0; + uint16_t regid1, regid2; + /* PHY has been enabled by hw_init. Figure out address first */ + for(; phy_addr < 32; phy_addr++) { + read_phy(PHY_PHYSID1, ®id1); + read_phy(PHY_PHYSID2, ®id2); + + if (((regid1 == 0x0000u) && (regid2 == 0x0000u)) || + ((regid1 == 0x3FFFu) && (regid2 == 0x0000u)) || + ((regid1 == 0x0000u) && (regid2 == 0x3FFFu)) || + ((regid1 == 0x3FFFu) && (regid2 == 0x3FFFu)) || + ((regid1 == 0xFFFFu) && (regid2 == 0x0000u)) || + ((regid1 == 0x0000u) && (regid2 == 0xFFFFu)) || + ((regid1 == 0x3FFFu) && (regid2 == 0xFFFFu)) || + ((regid1 == 0xFFFFu) && (regid2 == 0xFFFFu))) { + continue; + } else { + break; + } + } + + if(phy_addr >= 32) { + /* no PHY found */ + this->phy_addr = 0xFF; + return; + } else { + this->phy_addr = phy_addr; + } + + /* Reset PHY */ + write_phy(PHY_BMCR, BMCR_RESET); + read_phy(PHY_BMCR, ®id1); + + /* wait for PHY to come out of reset */ + while(regid1 & BMCR_RESET) { + osDelay(2); + read_phy(PHY_BMCR, ®id1); + } + + /* Enable PHY */ + if(regid1 & BMCR_PDOWN) { + write_phy(PHY_BMCR, regid1 & (~BMCR_PDOWN)); + } + + /* Set up auto-negotiation */ + read_phy(PHY_BMCR, ®id1); + regid1 |= BMCR_ANENABLE | BMCR_ANRESTART; + write_phy(PHY_BMCR, regid1); +} + +void SL_EMAC::write_phy(uint8_t reg_addr, uint16_t data) +{ + unsigned int timeout; + + ETH->PHYMNGMNT = ETH_PHYMNGMNT_WRITE0_DEFAULT + | ETH_PHYMNGMNT_WRITE1 + | (0x01 << _ETH_PHYMNGMNT_OPERATION_SHIFT) + | ((phy_addr << _ETH_PHYMNGMNT_PHYADDR_SHIFT) + & _ETH_PHYMNGMNT_PHYADDR_MASK) + | ((reg_addr << _ETH_PHYMNGMNT_REGADDR_SHIFT) + & _ETH_PHYMNGMNT_REGADDR_MASK) + | (0x2 << _ETH_PHYMNGMNT_WRITE10_SHIFT) + | (data & _ETH_PHYMNGMNT_PHYRWDATA_MASK); + + for(timeout = 0; timeout < 10000u; timeout++) { + if(ETH->NETWORKSTATUS & ETH_NETWORKSTATUS_MANDONE) { + break; + } + } +} + +void SL_EMAC::read_phy(uint8_t reg_addr, uint16_t *data) +{ + unsigned int timeout; + + ETH->PHYMNGMNT = ETH_PHYMNGMNT_WRITE0_DEFAULT + | ETH_PHYMNGMNT_WRITE1 + | (0x02 << _ETH_PHYMNGMNT_OPERATION_SHIFT) + | ((phy_addr << _ETH_PHYMNGMNT_PHYADDR_SHIFT) + & _ETH_PHYMNGMNT_PHYADDR_MASK) + | ((reg_addr << _ETH_PHYMNGMNT_REGADDR_SHIFT) + & _ETH_PHYMNGMNT_REGADDR_MASK) + | (0x2 << _ETH_PHYMNGMNT_WRITE10_SHIFT); + + for(timeout = 0; timeout < 10000u; timeout++) { + if(ETH->NETWORKSTATUS & ETH_NETWORKSTATUS_MANDONE) { + break; + } + } + + *data = ETH->PHYMNGMNT & _ETH_PHYMNGMNT_PHYRWDATA_MASK; +} + +void SL_EMAC::link_state_poll(void) +{ + uint16_t phy_val, link_val; + + /* read BMSR twice, since it needs to latch */ + read_phy(PHY_BMSR, &phy_val); + read_phy(PHY_BMSR, &phy_val); + + if((phy_val & BMSR_LSTATUS) == 0) { + /* link is down */ + tr_debug("link down"); + if(connected && emac_link_state_cb) { + emac_link_state_cb(false); + /* TODO: Reset all buffers here */ + /* For now, this is not a problem. In-transit buffers will + * still be sent the next time the link comes up, so the + * only impact is that we'd be sending stale packets. */ + } + connected = false; + return; + } + + /* link is up, get speed and duplex status */ + read_phy(PHY_ANAR, &phy_val); + read_phy(PHY_ANLPAR, &link_val); + + link_val &= (ANLPAR_100BASE4 | + ANLPAR_100FULL | + ANLPAR_100HALF | + ANLPAR_10FULL | + ANLPAR_10HALF); + + phy_val &= link_val; + + uint32_t old_link_state = ETH->NETWORKCFG & 0x3; + + if (phy_val >= ANLPAR_100FULL) { + /* 100 mbit full duplex */ + if (old_link_state != 0x3 || !connected) { + tr_debug("renegotiated to 100 full"); + ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x3; + } + } else if (phy_val >= ANLPAR_100HALF) { + /* 100 mbit half duplex */ + if (old_link_state != 0x1 || !connected) { + tr_debug("renegotiated to 100 half"); + ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x1; + } + } else if (phy_val >= ANLPAR_10FULL) { + /* 10 mbit full duplex */ + if (old_link_state != 0x2 || !connected) { + tr_debug("renegotiated to 10 full"); + ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x2; + } + } else { + /* 10 mbit half duplex */ + if (old_link_state != 0x0 || !connected) { + tr_debug("renegotiated to 10 half"); + ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x0; + } + } + + if(!connected && emac_link_state_cb) { + tr_debug("link up"); + emac_link_state_cb(true); + } + connected = true; +} + +// ----------------------------------------------------------------------------- +// Receive +// ----------------------------------------------------------------------------- + +/* Handled inside processing thread */ + +// ----------------------------------------------------------------------------- +// Send +// ----------------------------------------------------------------------------- +bool SL_EMAC::link_out(emac_mem_buf_t *buf) +{ + size_t num_bufs = 1, i; + emac_mem_buf_t * next = buf; + + /* If the link is down (or going down), don't even attempt sending anything */ + if(!up) { + tr_debug("Trying to send a packet while link is down"); + memory_manager->free(buf); + return false; + } + + /* Figure out how many buffers the buffer consists of */ + while((next = memory_manager->get_next(next)) != (emac_mem_buf_t*)NULL) { + num_bufs++; + } + + if(num_bufs >= SL_ETH_NUM_TX_BD) { + /* We've been passed more chained buffers than we can handle */ + tr_err("More TX buffers passed than provisioned!"); + memory_manager->free(buf); + return false; + } + + /* Wait for previous packet to finish transmitting */ + if (!tx_sem.try_acquire_for(100)) { + tr_warn("TX process didn't complete within 100ms"); + memory_manager->free(buf); + return false; + } + + tr_debug("Sending packet of %d bytes over %d buffers", memory_manager->get_total_len(buf), num_bufs); + + /* Set up TX descriptors with buffer, keep track of buffer reference */ + tx_buf = buf; + for(i = 0; i < num_bufs; i++) { + uint32_t statusword = memory_manager->get_len(buf) & 0x3FFF; + + if(i == (SL_ETH_NUM_TX_BD-1)) { + /* Mark as last BD in list */ + statusword |= (0x1 << 30); + } + if(i == num_bufs - 1) { + /* Mark as last BD for this frame */ + statusword |= (0x1 << 15); + } + + tx_bds[i].addr = (uint32_t)memory_manager->get_ptr(buf); + tx_bds[i].status = statusword; + + buf = memory_manager->get_next(buf); + } + + /* (Re-)Kick off ETH TX */ + ETH->TXQPTR = (uint32_t)tx_bds; + ETH->NETWORKCTRL |= ETH_NETWORKCTRL_TXSTRT; + return true; +} + +// ----------------------------------------------------------------------------- +// Multicast manipulation +// ----------------------------------------------------------------------------- +static uint8_t sl_eth_calc_hash(const uint8_t* const mac) +{ + return (uint8_t)(( (mac[0] & 0x3F) & 0x3F) + ^ ((((mac[0] >> 6) & 0x3) | ((mac[1] & 0xF) << 2)) & 0x3F) + ^ ((((mac[1] >> 4) & 0xF) | ((mac[2] & 0x3) << 4)) & 0x3F) + ^ ((((mac[2] >> 2) & 0x3F)) & 0x3F) + ^ ((mac[3] & 0x3F) & 0x3F) + ^ ((((mac[3] >> 6) & 0x3) | ((mac[4] & 0xF) << 2)) & 0x3F) + ^ ((((mac[4] >> 4) & 0xF) | ((mac[5] & 0x3) << 4)) & 0x3F) + ^ ((((mac[5] >> 2) & 0x3F)) & 0x3F)); +} + +void SL_EMAC::add_multicast_group(const uint8_t *address) +{ + uint8_t bitnr; + /* Calculate bit number for hash of this address */ + bitnr = sl_eth_calc_hash(address); + /* Increment refcnt */ + if (mcast_hash_refcnt[bitnr] == 0) { + if(bitnr > 31) { + ETH->HASHTOP |= (0x1 << (bitnr - 32)); + } else { + ETH->HASHBOTTOM |= (0x1 << bitnr); + } + } + mcast_hash_refcnt[bitnr]++; +} + +void SL_EMAC::remove_multicast_group(const uint8_t *address) +{ + uint8_t bitnr; + /* Calculate bit number for hash of this address */ + bitnr = sl_eth_calc_hash(address); + /* Decrement refcnt, remove bit if 0 */ + if(mcast_hash_refcnt[bitnr] == 1) { + mcast_hash_refcnt[bitnr] = 0; + if(bitnr > 31) { + ETH->HASHTOP &= ~(0x1 << (bitnr - 32)); + } else { + ETH->HASHBOTTOM &= ~(0x1 << bitnr); + } + } else { + mcast_hash_refcnt[bitnr]--; + } +} + +void SL_EMAC::set_all_multicast(bool all) +{ + uint32_t bottom = 0, top = 0; + + if(all == true) { + /* temporarily allow all packets to get processed */ + tr_debug("Accept all multicast packets"); + top = 0xFFFFFFFFUL; + bottom = 0xFFFFFFFFUL; + } else { + /* Revert to what was in the refcount */ + tr_debug("Revert to multicast filtering"); + size_t i = 0; + for(; i < 32; i++) { + if(mcast_hash_refcnt[i] > 0) { + bottom |= (1 << i); + } + } + for(; i < 64; i++) { + if(mcast_hash_refcnt[i-32] > 0) { + top |= (1 << (i-32)); + } + } + } + + /* Commit to peripheral */ + ETH->HASHTOP = top; + ETH->HASHBOTTOM = bottom; +} + +// ----------------------------------------------------------------------------- +// MAC manipulation +// ----------------------------------------------------------------------------- +uint8_t SL_EMAC::get_hwaddr_size() const +{ + // Ethernet uses EUI48 + return 6; +} + +bool SL_EMAC::get_hwaddr(uint8_t *addr) const +{ + if (DEVINFO->EUI48L != 0xFFFFFFFF) { + addr[0] = DEVINFO->EUI48H >> 8; + addr[1] = DEVINFO->EUI48H >> 0; + addr[2] = DEVINFO->EUI48L >> 24; + addr[3] = DEVINFO->EUI48L >> 16; + addr[4] = DEVINFO->EUI48L >> 8; + addr[5] = DEVINFO->EUI48L >> 0; + } else { + addr[0] = DEVINFO->UNIQUEH >> 24; + addr[1] = DEVINFO->UNIQUEH >> 16; + addr[2] = DEVINFO->UNIQUEH >> 8; + addr[3] = DEVINFO->UNIQUEL >> 16; + addr[4] = DEVINFO->UNIQUEL >> 8; + addr[5] = DEVINFO->UNIQUEL >> 0; + } + return true; +} + +void SL_EMAC::set_hwaddr(const uint8_t *addr) +{ + tr_debug("Setting MAC address %02x:%02x:%02x:%02x:%02x:%02x", + addr[0], + addr[1], + addr[2], + addr[3], + addr[4], + addr[5]); + ETH->SPECADDR1BOTTOM = ((uint32_t)addr[0] << (0)) | + ((uint32_t)addr[1] << (8)) | + ((uint32_t)addr[2] << (16))| + ((uint32_t)addr[3] << (24)); + + ETH->SPECADDR1TOP = ((uint32_t)addr[4] << (0)) | + ((uint32_t)addr[5] << (8)); +} + +// ----------------------------------------------------------------------------- +// Boilerplate +// ----------------------------------------------------------------------------- +SL_EMAC::SL_EMAC() + : thread(0), + tx_sem(1, 1), + phy_addr(0xFF), + rx_idx(0), + mcast_hash_refcnt(), + emac_link_input_cb(NULL), + emac_link_state_cb(NULL), + memory_manager(NULL), + connected(false), + up(false) +{ + +} + +uint32_t SL_EMAC::get_mtu_size() const +{ + return SL_ETH_MTU; +} + +uint32_t SL_EMAC::get_align_preference() const +{ + return SL_ETH_ALIGN; +} + +void SL_EMAC::get_ifname(char *name, uint8_t size) const +{ + memcpy(name, SL_ETH_IF_NAME, (size < sizeof(SL_ETH_IF_NAME)) ? size : sizeof(SL_ETH_IF_NAME)); +} + +void SL_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) +{ + emac_link_input_cb = input_cb; +} + +void SL_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) +{ + emac_link_state_cb = state_cb; +} + +void SL_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) +{ + memory_manager = &mem_mngr; +} + +SL_EMAC &SL_EMAC::get_instance() { + static SL_EMAC emac; + return emac; +} + +MBED_WEAK EMAC &EMAC::get_default_instance() { + return SL_EMAC::get_instance(); +} + +#endif //ETH_PRESENT diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.h b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.h new file mode 100644 index 0000000..4fdc6d7 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac.h @@ -0,0 +1,256 @@ +/***************************************************************************//** + * @file sl_eth_phy.h + ******************************************************************************* + * @section License + * modifications (C) Copyright 2018 Silicon Labs, http://www.silabs.com + * original Copyright (c) 2015 ARM Limited + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef SL_EMAC_H_ +#define SL_EMAC_H_ + +#include "EMAC.h" +#include "rtos/Semaphore.h" +#include "rtos/Mutex.h" + +class SL_EMAC : public EMAC { +public: + SL_EMAC(); + + static SL_EMAC &get_instance(); + + /** + * Return maximum transmission unit + * + * @return MTU in bytes + */ + virtual uint32_t get_mtu_size() const; + + /** + * Gets memory buffer alignment preference + * + * Gets preferred memory buffer alignment of the Emac device. + * IP stack may or may not align link out memory buffer chains + * using the alignment. + * + * @return Memory alignment requirement in bytes + */ + virtual uint32_t get_align_preference() const; + + /** + * Return interface name + * + * @param name Pointer to where the name should be written + * @param size Maximum number of character to copy + */ + virtual void get_ifname(char *name, uint8_t size) const; + + /** + * Returns size of the underlying interface HW address size. + * + * @return HW address size in bytes + */ + virtual uint8_t get_hwaddr_size() const; + + /** + * Return interface-supplied HW address + * + * Copies HW address to provided memory, @param addr has to be of correct + * size see @a get_hwaddr_size + * + * HW address need not be provided if this interface does not have its own + * HW address configuration; stack will choose address from central system + * configuration if the function returns false and does not write to addr. + * + * @param addr HW address for underlying interface + * @return true if HW address is available + */ + virtual bool get_hwaddr(uint8_t *addr) const; + + /** + * Set HW address for interface + * + * Provided address has to be of correct size, see @a get_hwaddr_size + * + * Called to set the MAC address to actually use - if @a get_hwaddr is + * provided the stack would normally use that, but it could be overridden, + * eg for test purposes. + * + * @param addr Address to be set + */ + virtual void set_hwaddr(const uint8_t *addr); + + /** + * Sends the packet over the link + * + * That can not be called from an interrupt context. + * + * @param buf Packet to be send + * @return True if the packet was send successfully, False otherwise + */ + virtual bool link_out(emac_mem_buf_t *buf); + + /** + * Initializes the HW + * + * @return True on success, False in case of an error. + */ + virtual bool power_up(); + + /** + * Deinitializes the HW + * + */ + virtual void power_down(); + + /** + * Sets a callback that needs to be called for packets received for that + * interface + * + * @param input_cb Function to be register as a callback + */ + virtual void set_link_input_cb(emac_link_input_cb_t input_cb); + + /** + * Sets a callback that needs to be called on link status changes for given + * interface + * + * @param state_cb Function to be register as a callback + */ + virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); + + /** Add device to a multicast group + * + * @param address A multicast group hardware address + */ + virtual void add_multicast_group(const uint8_t *address); + + /** Remove device from a multicast group + * + * @param address A multicast group hardware address + */ + virtual void remove_multicast_group(const uint8_t *address); + + /** Request reception of all multicast packets + * + * @param all True to receive all multicasts + * False to receive only multicasts addressed to specified groups + */ + virtual void set_all_multicast(bool all); + + /** Sets memory manager that is used to handle memory buffers + * + * @param mem_mngr Pointer to memory manager + */ + virtual void set_memory_manager(EMACMemoryManager &mem_mngr); + + osThreadId_t thread; /** Ethernet driver thread */ + +private: + + /* Instance variables */ + + /** Semaphore protecting the TX state. + * Not a mutex since we're posting from IRQ + */ + rtos::Semaphore tx_sem; + /** (R)MII address where the detected PHY is residing */ + uint8_t phy_addr; + /** Index in RX queue for next packet to read */ + uint8_t rx_idx; + + /** Multicast mask reference count. Multicast filtering is done using a hash + * bit, so multiple multicast addresses might map to the same bit. That's + * why there needs to be a reference count for every bit in the 64-bit mask + */ + uint8_t mcast_hash_refcnt[64]; + + /** Local reference to the buffer that's in the process of being sent */ + emac_mem_buf_t *tx_buf; + /** List of current RX buffers, which autonomously get filled by the + * Ethernet peripheral. + */ + emac_mem_buf_t *rx_bufs[SL_ETH_NUM_RX_BD]; + + typedef struct { + uint32_t addr; + uint32_t status; + } sl_eth_bd_t; + + /** Internal list of DMA descriptors for the RX buffer pool */ + sl_eth_bd_t rx_bds[SL_ETH_NUM_RX_BD]; + /** Internal list of DMA descriptors to point to the current buffer being + * sent */ + sl_eth_bd_t tx_bds[SL_ETH_NUM_TX_BD]; + + /**< Processing thread */ + mbed_rtos_storage_thread_t thread_cb; + + /**< Callback for incoming data */ + emac_link_input_cb_t emac_link_input_cb; + /**< Callback for link state change */ + emac_link_state_change_cb_t emac_link_state_cb; + + /**< Memory manager instance */ + EMACMemoryManager *memory_manager; + + bool connected; + bool up; + + /* private functions */ + /** + * Thread to de-escalate Ethernet peripheral IRQ's + */ + static void eth_thread(void* instance); + + /** + * This function polls the (R)MII bus for the first + * available attached PHY chip, resets and enables the PHY + * in auto-negotiation mode. + */ + void phy_init(void); + + /** + * Write to detected PHY register. Nop if no PHY initialized. + */ + void write_phy(uint8_t reg_addr, uint16_t data); + + /** + * Read from detected PHY register. Nop if no PHY initialized. + */ + void read_phy(uint8_t reg_addr, uint16_t *data); + + /** + * This function checks the detected PHY for its + * current link status. Nop if no PHY was previously detected. + * Fires callback set by set_link_state_cb on change in link state. + */ + void link_state_poll(void); + + /** + * Initializes buffer structures + */ + void data_init(void); + + /** + * De-initializes buffer structures + */ + void data_deinit(void); +}; + +#endif /* SL_EMAC_H_ */ diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac_config.h b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac_config.h new file mode 100644 index 0000000..86c7d99 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_emac_config.h @@ -0,0 +1,52 @@ +/***************************************************************************//** + * @file sl_emac_config.h + ******************************************************************************* + * @section License + * (C) Copyright 2018 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef SL_EMAC_CONFIG_H +#define SL_EMAC_CONFIG_H +// ----------------------------------------------------------------------------- +// Config options +// ----------------------------------------------------------------------------- +/** Number of descriptors in receive list */ +#define SL_ETH_NUM_RX_BD (16) +/** Number of descriptors in transmit list */ +#define SL_ETH_NUM_TX_BD (8) +/** Size of one buffer in a buffer descriptor (must be multiple of 64) */ +#define SL_ETH_RX_BUF_SIZE (1536) +/** Timeout in milliseconds for polling the PHY link status */ +#define SL_ETH_LINK_POLL_PERIOD_MS (500) +/** Default Ethernet worker thread stack size in bytes */ +#include "mbed_trace.h" +#if MBED_CONF_MBED_TRACE_ENABLE == 1 +#define SL_ETH_THREAD_STACKSIZE (768) +#else +#define SL_ETH_THREAD_STACKSIZE (512) +#endif +/** Default Ethernet worker thread stack priority */ +#define SL_ETH_THREAD_PRIORITY (osPriorityHigh) +/** Name of interface */ +#define SL_ETH_IF_NAME "sl" +/** Required alignment (in bytes) for packet buffers */ +#define SL_ETH_ALIGN (16) +/** Link MTU */ +#define SL_ETH_MTU (1500) + +#endif /* SL_EMAC_CONFIG_H */ diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.c b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.c new file mode 100644 index 0000000..ffb7f7f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.c @@ -0,0 +1,157 @@ +/***************************************************************************//** + * @file sl_eth_hw.c + ******************************************************************************* + * @section License + * (C) Copyright 2017 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#include "sl_eth_hw.h" +#include "device.h" +#include "em_cmu.h" +#include "em_gpio.h" +#include "hal/gpio_api.h" + +#if defined(ETH_PRESENT) + +void sl_eth_hw_init(void) +{ + /* Turn on clocks to ETH */ + CMU_ClockEnable(cmuClock_HFPER, true); + CMU_ClockEnable(cmuClock_ETH, true); + CMU_ClockEnable(cmuClock_GPIO, true); + + /* Drive RMII from the MCU-side 50MHz clock */ + GPIO_PinModeSet(AF_CMU_CLK2_PORT(MBED_CONF_SL_ETH_REFCLK_LOCATION), + AF_CMU_CLK2_PIN(MBED_CONF_SL_ETH_REFCLK_LOCATION), + gpioModePushPull, 0); + CMU->CTRL |= CMU_CTRL_CLKOUTSEL2_HFXO; + CMU->ROUTELOC0 = (CMU->ROUTELOC0 & ~_CMU_ROUTELOC0_CLKOUT2LOC_MASK) | (MBED_CONF_SL_ETH_REFCLK_LOCATION << _CMU_ROUTELOC0_CLKOUT2LOC_SHIFT); + CMU->ROUTEPEN |= CMU_ROUTEPEN_CLKOUT2PEN; + + ETH->CTRL = ETH_CTRL_GBLCLKEN | ETH_CTRL_MIISEL_RMII; + + /* Set pins to ETH for RMII config */ + GPIO_PinModeSet(AF_ETH_RMIICRSDV_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIICRSDV_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeInput, 0); /* CRS_DV */ + GPIO_PinModeSet(AF_ETH_RMIITXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModePushPull, 0); /* TXD0 */ + GPIO_PinModeSet(AF_ETH_RMIITXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModePushPull, 0); /* TXD1 */ + GPIO_PinModeSet(AF_ETH_RMIITXEN_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXEN_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModePushPull, 0); /* TX_EN */ + GPIO_PinModeSet(AF_ETH_RMIIRXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeInput, 0); /* RXD0 */ + GPIO_PinModeSet(AF_ETH_RMIIRXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeInput, 0); /* RXD1 */ + GPIO_PinModeSet(AF_ETH_RMIIRXER_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXER_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeInput, 0); /* RX_ER */ + + /* Setup route locations and enable pins */ + ETH->ROUTELOC1 = (MBED_CONF_SL_ETH_RMII_LOCATION << _ETH_ROUTELOC1_RMIILOC_SHIFT) + | (MBED_CONF_SL_ETH_MDIO_LOCATION << _ETH_ROUTELOC1_MDIOLOC_SHIFT); + ETH->ROUTEPEN = ETH_ROUTEPEN_RMIIPEN | ETH_ROUTEPEN_MDIOPEN; + ETH->ROUTEPEN = ETH_ROUTEPEN_RMIIPEN | ETH_ROUTEPEN_MDIOPEN; + + /* Setup the MDIO pins */ + GPIO_PinModeSet(AF_ETH_MDIO_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), + AF_ETH_MDIO_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), + gpioModePushPull, 0); /* MDIO */ + GPIO_PinModeSet(AF_ETH_MDC_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), + AF_ETH_MDC_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), + gpioModePushPull, 0); /* MDC */ + + /* Enable the PHY on the STK */ +#if defined(MBED_CONF_SL_ETH_PHY_POWER_PIN) + gpio_t pwr_pin; + gpio_init_out_ex(&pwr_pin, MBED_CONF_SL_ETH_PHY_POWER_PIN, 1); +#endif + +#if defined(MBED_CONF_SL_ETH_PHY_ENABLE_PIN) + gpio_t en_pin; + gpio_init_out_ex(&en_pin, MBED_CONF_SL_ETH_PHY_ENABLE_PIN, 1); +#endif +} + +void sl_eth_hw_deinit(void) +{ + /* Turn off PHY */ +#if defined(MBED_CONF_SL_ETH_PHY_POWER_PIN) + gpio_t pwr_pin; + gpio_init(&pwr_pin, MBED_CONF_SL_ETH_PHY_ENABLE_PIN); + gpio_write(&pwr_pin, 0); + gpio_mode(&pwr_pin, Disabled); +#endif + +#if defined(MBED_CONF_SL_ETH_PHY_ENABLE_PIN) + gpio_t en_pin; + gpio_init(&en_pin, MBED_CONF_SL_ETH_PHY_POWER_PIN); + gpio_write(&en_pin, 0); + gpio_mode(&en_pin, Disabled); +#endif + + /* Turn off MAC */ + ETH->ROUTEPEN = 0; + ETH->CTRL = _ETH_CTRL_RESETVALUE; + + /* Turn off clock */ + CMU->CTRL &= ~CMU_CTRL_CLKOUTSEL2_HFXO; + CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT2PEN; + + CMU_ClockEnable(cmuClock_ETH, false); + + /* Set used pins back to disabled */ + GPIO_PinModeSet(AF_ETH_MDIO_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), + AF_ETH_MDIO_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), + gpioModeDisabled, 0); /* MDIO */ + GPIO_PinModeSet(AF_ETH_MDC_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), + AF_ETH_MDC_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), + gpioModeDisabled, 0); /* MDC */ + GPIO_PinModeSet(AF_ETH_RMIICRSDV_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIICRSDV_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* CRS_DV */ + GPIO_PinModeSet(AF_ETH_RMIITXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* TXD0 */ + GPIO_PinModeSet(AF_ETH_RMIITXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* TXD1 */ + GPIO_PinModeSet(AF_ETH_RMIITXEN_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIITXEN_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* TX_EN */ + GPIO_PinModeSet(AF_ETH_RMIIRXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* RXD0 */ + GPIO_PinModeSet(AF_ETH_RMIIRXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* RXD1 */ + GPIO_PinModeSet(AF_ETH_RMIIRXER_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), + AF_ETH_RMIIRXER_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), + gpioModeDisabled, 0); /* RX_ER */ + GPIO_PinModeSet(AF_CMU_CLK2_PORT(MBED_CONF_SL_ETH_REFCLK_LOCATION), + AF_CMU_CLK2_PIN(MBED_CONF_SL_ETH_REFCLK_LOCATION), + gpioModeDisabled, 0); /* REF_CLK */ +} + +#endif //ETH_PRESENT diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.h b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.h new file mode 100644 index 0000000..ebca47f --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_hw.h @@ -0,0 +1,44 @@ +/***************************************************************************//** + * @file sl_eth_hw.h + ******************************************************************************* + * @section License + * (C) Copyright 2018 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef SL_ETH_HW_H +#define SL_ETH_HW_H + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * Sets up hardware pins and configures internal clocks + */ +void sl_eth_hw_init(void); + +/** + * Releases hardware pins and turns off internal clocks + */ +void sl_eth_hw_deinit(void); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_phy.h b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_phy.h new file mode 100644 index 0000000..3e76859 --- /dev/null +++ b/connectivity/drivers/emac/TARGET_Silicon_Labs/sl_eth_phy.h @@ -0,0 +1,94 @@ +/***************************************************************************//** + * @file sl_eth_phy.h + ******************************************************************************* + * @section License + * (C) Copyright 2017 Silicon Labs, http://www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +#ifndef __SL_ETH_PHY_H__ +#define __SL_ETH_PHY_H__ + +#define PHY_BMCR 0x00u /* Basic mode control reg. */ +#define PHY_BMSR 0x01u /* Basic mode status reg. */ +#define PHY_PHYSID1 0x02u /* PHYS ID 1 reg. */ +#define PHY_PHYSID2 0x03u /* PHYS ID 2 reg. */ +#define PHY_ANAR 0x04u /* Advertisement control reg. */ +#define PHY_ANLPAR 0x05u /* Link partner ability reg. */ +#define PHY_ANER 0x06u /* Expansion reg. */ +#define PHY_ANNPTR 0x07u /* Next page transmit reg. */ + +/* -------------- PHY_BMCR REGISTER BITS -------------- */ +#define BMCR_CTST (0x1 << 7) /* Collision test. */ +#define BMCR_FULLDPLX (0x1 << 8) /* Full duplex. */ +#define BMCR_ANRESTART (0x1 << 9) /* Auto negotiation restart. */ +#define BMCR_ISOLATE (0x1 << 10) /* Disconnect Phy from MII. */ +#define BMCR_PDOWN (0x1 << 11) /* Power down. */ +#define BMCR_ANENABLE (0x1 << 12) /* Enable auto negotiation. */ +#define BMCR_SPEED100 (0x1 << 13) /* Select 100Mbps. */ +#define BMCR_LOOPBACK (0x1 << 14) /* TXD loopback bits. */ +#define BMCR_RESET (0x1 << 15) /* Reset. */ + +/* -------------- PHY_BMSR REGISTER BITS -------------- */ +#define BMSR_ERCAP (0x1 << 0) /* Ext-reg capability. */ +#define BMSR_JCD (0x1 << 1) /* Jabber detected. */ +#define BMSR_LSTATUS (0x1 << 2) /* Link status. */ +#define BMSR_ANEGCAPABLE (0x1 << 3) /* Able to do auto-negotiation. */ +#define BMSR_RFAULT (0x1 << 4) /* Remote fault detected. */ +#define BMSR_ANEGCOMPLETE (0x1 << 5) /* Auto-negotiation complete. */ +#define BMSR_10HALF (0x1 << 11) /* Can do 10mbps, half-duplex. */ +#define BMSR_10FULL (0x1 << 12) /* Can do 10mbps, full-duplex. */ +#define BMSR_100HALF (0x1 << 13) /* Can do 100mbps, half-duplex. */ +#define BMSR_100FULL (0x1 << 14) /* Can do 100mbps, full-duplex. */ +#define BMSR_100BASE4 (0x1 << 15) /* Can do 100mbps, 4k packets. */ + +/* -------------- PHY_ANAR REGISTER BITS -------------- */ +#define ANAR_SLCT 0x001Fu /* Selector bits. */ +#define ANAR_CSMA DEF_BIT_04 /* Only selector supported. */ +#define ANAR_10HALF DEF_BIT_05 /* Try for 10mbps half-duplex. */ +#define ANAR_10FULL DEF_BIT_06 /* Try for 10mbps full-duplex. */ +#define ANAR_100HALF DEF_BIT_07 /* Try for 100mbps half-duplex. */ +#define ANAR_100FULL DEF_BIT_08 /* Try for 100mbps full-duplex. */ +#define ANAR_100BASE4 DEF_BIT_09 /* Try for 100mbps 4k packets. */ +#define ANAR_RFAULT DEF_BIT_13 /* Say we can detect faults. */ +#define ANAR_LPACK DEF_BIT_14 /* Ack link partners response. */ +#define ANAR_NPAGE DEF_BIT_15 /* Next page bit. */ + +#define ANAR_FULL (ANAR_100FULL | ANAR_10FULL | ANAR_CSMA) +#define ANAR_ALL (ANAR_100BASE4 | ANAR_100FULL | ANAR_10FULL | ANAR_100HALF | ANAR_10HALF) + +/* ------------- PHY_ANLPAR REGISTER BITS ------------- */ +#define ANLPAR_10HALF (0x1 << 5) /* Can do 10mbps half-duplex. */ +#define ANLPAR_10FULL (0x1 << 6) /* Can do 10mbps full-duplex. */ +#define ANLPAR_100HALF (0x1 << 7) /* Can do 100mbps half-duplex. */ +#define ANLPAR_100FULL (0x1 << 8) /* Can do 100mbps full-duplex. */ +#define ANLPAR_100BASE4 (0x1 << 9) /* Can do 100mbps 4k packets. */ +#define ANLPAR_RFAULT (0x1 << 13) /* Link partner faulted. */ +#define ANLPAR_LPACK (0x1 << 14) /* Link partner acked us. */ +#define ANLPAR_NPAGE (0x1 << 15) /* Next page bit. */ + +#define ANLPAR_DUPLEX (ANLPAR_10FULL | ANLPAR_100FULL) +#define ANLPAR_100 (ANLPAR_100FULL | ANLPAR_100HALF | ANLPAR_100BASE4) + +/* -------------- PHY_ANER REGISTER BITS -------------- */ +#define ANER_NWAY (0x1 << 0) /* Can do N-way auto-negotiation. */ +#define ANER_LCWP (0x1 << 1) /* Got new RX page code word. */ +#define ANER_ENABLENPAGE (0x1 << 2) /* This enables npage words. */ +#define ANER_NPCAPABLE (0x1 << 3) /* Link partner supports npage. */ +#define ANER_MFAULTS (0x1 << 4) /* Multiple faults detected. */ + +#endif diff --git a/features/netsocket/emac-drivers/README.md b/features/netsocket/emac-drivers/README.md deleted file mode 100644 index 7da4f06..0000000 --- a/features/netsocket/emac-drivers/README.md +++ /dev/null @@ -1,185 +0,0 @@ -# mbed OS Ethernet MAC (EMAC) drivers - -This document describes how to port and test an Ethernet MAC (EMAC) driver to -mbed OS. It is based on work on the feature-emac branch as of mbed OS 5.8, -which is intended to be merged into mbed OS 5.9 - -The scope of this document is limited to Ethernet (IEEE 802.3) or Ethernet-like -devices such as Wi-Fi (IEEE 802.11), where the device presents a MAC interface -to send and receive frames, and this will be used by one of the onboard -network stacks that runs on mbed OS on the host processor. - -(If the device has an off-board network stack, a driver would need to implement -`NetworkStack` directly instead to pass network calls to that offboard -stack). - -## Abstractions - -The EMAC interface is designed to abstract network stacks and drivers, and to -easily permit multiple instances. The key API classes are: - -* `NetworkInterface` - an mbed OS network interface of any type -* `NetworkStack` - an mbed OS network stack of any type (may be off-board) -* `OnboardNetworkStack` - an on-board network stack -* `EMAC` - an Ethernet MAC device driver -* `EMACMemoryManager` - a memory manager used to pass data between driver and stack -* `EMACInterface`- a `NetworkInterface` that uses an `EMAC` driver and an `OnboardNetworkStack` - -## The EMAC driver core - -The first step in the port is to create a driver class that can be instantiated -to control your device. This must be derived from class `EMAC`. -This API is used by a network stack (or test framework) to control your driver. - -The EMAC-derived driver would normally be installed in -features/netsocket/emac-drivers, often in a `TARGET_XXX` directory. - -Class EMAC is entirely abstract - you need to implement about a dozen calls -to activate the driver, send and receive packets, and perform other control -and information functions. - -There are also callback registration functions for upcalls from the driver - the -stack can register callback functions for packet reception and link status -changes. - - -## The EMAC memory manager - -For the send and receive paths, data is transferred in memory buffers controlled -via an `EMACMemoryManager` object. The network stack using an EMAC driver -provides it with a reference to the memory manager in use before powering up - -this will be constant as long as the EMAC is powered up. - -On the output call, the EMAC driver is given ownership of a buffer chain - it -must free the chain when it has finished with the data. The data may or may -not be contiguous. A driver can express alignment preferences for outgoing data, -but the network stack is not required to meet these prefernces, so a driver -relying on alignment may need a slow path that copies data into an aligned -(or contiguous) buffer. - -For reception, the EMAC driver must allocate memory from the `EMACMemoryManager` -to store the received packets - this is then passed to the link input callback, -which will free it. By preference this memory should be allocated using the pool, -but if contiguous memory is required it can be allocated from the heap. - - -## EthernetInterface - -If your driver is a pure Ethernet driver, there is no further implementation -required. The class `EthernetInterface` can use any `EMAC` driver to provide -an mbed OS `NetworkInterface`: - - MyEMAC my_emac(params); - EthernetInterface net(&my_emac); - - net.connect(); - -This will attach the default network stack (normally lwIP - the other -current alternative is Nanostack) to the specified EMAC driver, and provide all -the generic `NetworkInterface` and `NetworkStack` APIs. - -## Being the default EMAC / EthernetInterface - -To make your EMAC the default for applications you should define the static function -`EMAC::get_default_instance()` to return an instance of your emac, eg: - - MBED_WEAK EMAC &EMAC::get_default_instance() - { - static MyEMAC my_emac(params); - return &my_emac; - } - -This permits this example application code to work: - - EthernetInterface net; // uses EMAC::get_default_instance() - net.connect(); - -This definition would normally be gated by a target label of some sort. As -target code, your definition of EMAC::get_default_instance() must be weak - -this permits it to be overridden by application code. - -## Wi-Fi interfaces - -As a Wi-Fi interface, a little more work is required - at a minimum you need -to implement the extra configuration calls in `WiFiInterface`. This -is because the network stacks and EMAC APIs are only related to the -Ethernet-like data path - they have no knowledge of any other configuration -mechanisms and assume they are already set up. - -To do this, you should create a C++ class that inherits from both -`WiFiInterface` and `EMACInterface`. The `EMACInterface` is a helper class -that implements all the core `NetworkInterface` functionality for you. You -then just need to implement the extra `WiFiInterface` configuration methods. - -For reference, note that `EthernetInterface` also derives from -`EMACInterface`, but has no extra code as there is no extra configuration -required. - -As a Wi-fi driver, you will not normally be directly exposing your `EMAC` class - -it would not normally be declared as `EMAC::get_default_instance`, but you -would pass it to the constructor of your base `EMACInterface`. This then -will make it visible via the `get_emac` method. This is for test purposes, -meaning the test framework can do: - - MyWiFiInterface net; - net.set_credentials(); - EMAC &emac = net.get_emac(); - do_emac_test(emac); - -This must work in your driver - it must be possible to power up and use the -built-in EMAC directly without the `NetworkInterface::connect()` method being -invoked, as long as the credentials have been set. This structure will come naturally if -you just use the default `EMACInterface::connect()` implementation. - -Note also that your constructor must allow the network stack to be specified using -the same form as `EthernetInterface`: - - MyWiFiInterface(OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); - -## OnboardNetworkStack - -The precise details of the `OnboardNetworkStack` API should not concern -an EMAC driver writer - it provides the mechanism to bind a driver to a stack, and -the APIs needed to implement a `NetworkInterface`, but this is handled by -`EMACInterface`, either as a base class of your own `XXXInterface` or as -the base of `EthernetInterface`. - -## DEVICE_EMAC - -At present, as an interim measure, targets providing `EMAC::get_default_instance()` -should add "EMAC" in `device_has` in their `targets.json`. This activates -network tests in CI builds. - -This is subject to change, but is necessary in lieu of the previous typical -behaviour of gating tests on `FEATURE_LWIP`. - -## Tuning memory allocations - -Depending on its use of pool and heap memory, and other factors, a driver might -want to tune the configuration of particular network stacks. This can be done via -the `mbed_lib.json` of each network stack, using their `target_overrides` -section. - -## Testing - -The mbed OS tree contains Greentea-based tests that exercise the EMAC API -directly, and more general socket tests. - -See here for general Greentea information: - -See here for the emac tests: - - -Greentea socket tests are at: - - -The driver should also be exercised with real-world examples like - - -The driver should also be tested with both network stacks available in mbed OS, -as they will use the driver somewhat differently - try with the JSON option -`nsapi.default-stack` set to each of `LWIP` and `NANOSTACK`. - -Nanostack is IPv6 only. IPv6 operation should also be tested with lwIP, as this -is likely to reveal problems with multicast filtering that may not be spotted -by IPv4 or Nanostack. diff --git a/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp b/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp deleted file mode 100644 index 95ec2bf..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" -#include "fvp_emac.h" -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -using namespace std::chrono; - -/******************************************************************************** - * Internal data - ********************************************************************************/ - -#define THREAD_STACKSIZE 512 - -/* Flags for worker thread */ -#define FLAG_TX (0x1u << 0) -#define FLAG_RX (0x1u << 1) - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityNormal) - -#define PHY_TASK_PERIOD 200ms - - -fvp_EMAC::fvp_EMAC() : _thread(THREAD_PRIORITY, THREAD_STACKSIZE, NULL, "fvp_emac_thread") - -{ -} - -void fvp_EMAC::ethernet_callback(lan91_event_t event, void *param) -{ - fvp_EMAC *enet = static_cast(param); - switch (event) { - case LAN91_RxEvent: - enet->rx_isr(); - break; - case LAN91_TxEvent: - enet->tx_isr(); - break; - default: - break; - } -} - -/** \brief Ethernet receive interrupt handler */ -void fvp_EMAC::rx_isr() -{ - _thread.flags_set(FLAG_RX); -} - -/** \brief Ethernet transmit interrupt handler */ -void fvp_EMAC::tx_isr() -{ - _thread.flags_set(FLAG_TX); -} - -/** \brief Low level init of the MAC and PHY. */ -bool fvp_EMAC::low_level_init_successful() -{ - LAN91_init(); - LAN91_SetCallback(&fvp_EMAC::ethernet_callback, this); - return true; -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void fvp_EMAC::thread_function(void *pvParameters) -{ - struct fvp_EMAC *fvp_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = ThisThread::flags_wait_any(FLAG_RX | FLAG_TX); - if (flags & FLAG_RX) { - fvp_enet->packet_rx(); - } - } -} - - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the LWIP core. - */ -void fvp_EMAC::packet_rx() -{ - while (!LAN91_RxFIFOEmpty()) { - emac_mem_buf_t *temp_rxbuf = NULL; - uint32_t *rx_payload_ptr; - uint32_t rx_length = 0; - - temp_rxbuf = _memory_manager->alloc_heap(FVP_ETH_MAX_FLEN, LAN91_BUFF_ALIGNMENT); - - /* no memory been allocated*/ - if (NULL != temp_rxbuf) { - - rx_payload_ptr = (uint32_t *)_memory_manager->get_ptr(temp_rxbuf); - rx_length = _memory_manager->get_len(temp_rxbuf); - bool state; - -#ifdef LOCK_RX_THREAD - /* Get exclusive access */ - _TXLockMutex.lock(); -#endif - state = LAN91_receive_frame(rx_payload_ptr, &rx_length); - -#ifdef LOCK_RX_THREAD - _TXLockMutex.unlock(); -#endif - if (!state) { - _memory_manager->free(temp_rxbuf); - continue; - } else { - _memory_manager->set_len(temp_rxbuf, rx_length); - } - _emac_link_input_cb(temp_rxbuf); - } - } - LAN91_SetInterruptMasks(MSK_RCV); -} - - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent - */ -bool fvp_EMAC::link_out(emac_mem_buf_t *buf) -{ - // If buffer is chained or not aligned then make a contiguous aligned copy of it - if (_memory_manager->get_next(buf) || - reinterpret_cast(_memory_manager->get_ptr(buf)) % LAN91_BUFF_ALIGNMENT) { - emac_mem_buf_t *copy_buf; - copy_buf = _memory_manager->alloc_heap(_memory_manager->get_total_len(buf), LAN91_BUFF_ALIGNMENT); - if (NULL == copy_buf) { - _memory_manager->free(buf); - return false; - } - - // Copy to new buffer and free original - _memory_manager->copy(copy_buf, buf); - _memory_manager->free(buf); - buf = copy_buf; - } - - /* Save the buffer so that it can be freed when transmit is done */ - uint32_t *buffer; - uint32_t tx_length = 0; - bool state; - buffer = (uint32_t *)(_memory_manager->get_ptr(buf)); - tx_length = _memory_manager->get_len(buf); - - /* Get exclusive access */ - _TXLockMutex.lock(); - - /* Setup transfers */ - state = LAN91_send_frame(buffer, &tx_length); - _TXLockMutex.unlock(); - /* Restore access */ - - - if (!state) { - return false; - } - /* Free the buffer */ - _memory_manager->free(buf); - - return true; -} - -/** \brief PHY task monitoring the link */ -void fvp_EMAC::phy_task() -{ - // Get current status - lan91_phy_status_t connection_status; - connection_status = LAN91_GetLinkStatus(); - - if (connection_status != _prev_state && _emac_link_state_cb) { - _emac_link_state_cb(connection_status); - } - _prev_state = connection_status; -} - -bool fvp_EMAC::power_up() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - /* Start ethernet Worker thread */ - _thread.start(callback(&fvp_EMAC::thread_function, this)); - - /* Trigger thread to deal with any RX packets that arrived before thread was started */ - rx_isr(); - - /* PHY monitoring task */ - _prev_state = STATE_LINK_DOWN; - - mbed::mbed_event_queue()->call(mbed::callback(this, &fvp_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - ThisThread::sleep_for(10); - - _phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &fvp_EMAC::phy_task)); - - return true; -} - -uint32_t fvp_EMAC::get_mtu_size() const -{ - return LAN91_ETH_MTU_SIZE; -} - -uint32_t fvp_EMAC::get_align_preference() const -{ - return LAN91_BUFF_ALIGNMENT; -} - -void fvp_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, FVP_ETH_IF_NAME, (size < sizeof(FVP_ETH_IF_NAME)) ? size : sizeof(FVP_ETH_IF_NAME)); -} - -uint8_t fvp_EMAC::get_hwaddr_size() const -{ - return FVP_HWADDR_SIZE; -} - -bool fvp_EMAC::get_hwaddr(uint8_t *addr) const -{ - read_MACaddr(addr); - return true; -} - -void fvp_EMAC::set_hwaddr(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void fvp_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - _emac_link_input_cb = input_cb; -} - -void fvp_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - _emac_link_state_cb = state_cb; -} - -void fvp_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void fvp_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void fvp_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void fvp_EMAC::power_down() -{ - /* No-op at this stage */ -} - -void fvp_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - _memory_manager = &mem_mngr; -} - - -fvp_EMAC &fvp_EMAC::get_instance() -{ - static fvp_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return fvp_EMAC::get_instance(); -} - -/** @} */ - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h b/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h deleted file mode 100644 index 7f74007..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_FM/COMPONENT_LAN91C111/fvp_emac.h +++ /dev/null @@ -1,178 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FVP_EMAC_H_ -#define FVP_EMAC_H_ - -#include "EMAC.h" -#include "mbed.h" -#include "rtos/Mutex.h" -#include "lan91c111.h" - - -#define FVP_HWADDR_SIZE (6) -#define FVP_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame -#define FVP_ETH_IF_NAME "ARM0" - -class fvp_EMAC : public EMAC { -public: - fvp_EMAC(); - - static fvp_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - bool low_level_init_successful(); - void rx_isr(); - void tx_isr(); - void packet_rx(); - static void thread_function(void *pvParameters); - void phy_task(); - static void ethernet_callback(lan91_event_t event, void *param); - - Thread _thread; /* Processing thread */ - rtos::Mutex _TXLockMutex; /* TX critical section mutex */ - - emac_link_input_cb_t _emac_link_input_cb; /* Callback for incoming data */ - emac_link_state_change_cb_t _emac_link_state_cb; /* Link state change callback */ - - EMACMemoryManager *_memory_manager; /* Memory manager */ - - int _phy_task_handle; /* Handle for phy task event */ - lan91_phy_status_t _prev_state; -}; - -#endif /* FVP_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json deleted file mode 100644 index d54a278..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/mbed_lib.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "smsc9220-emac", - "config": { - "rx-ring-len": 1, - "tx-ring-len": 1 - } -} diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp deleted file mode 100644 index ca97bc6..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "mbed_interface.h" -#include "mbed_wait_api.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -#include "smsc9220_emac.h" -#include "smsc9220_eth_drv.h" - -#ifndef SMSC9220_ETH -#error "SMSC9220_ETH should be defined, check device_cfg.h!" -#endif - -#ifndef SMSC9220_Ethernet_Interrupt_Handler -#error "SMSC9220_Ethernet_Interrupt_Handler should be defined to platform's \ -Ethernet IRQ handler!" -#endif - -static SMSC9220_EMAC *board_emac_pointer = NULL; -const struct smsc9220_eth_dev_t* SMSC9220_EMAC::dev = &SMSC9220_ETH_DEV; - -extern "C" void SMSC9220_Ethernet_Interrupt_Handler(void) -{ - if (smsc9220_get_interrupt(SMSC9220_EMAC::dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL)) { - board_emac_pointer->rx_isr(); - smsc9220_clear_interrupt(SMSC9220_EMAC::dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - smsc9220_disable_interrupt(SMSC9220_EMAC::dev, - SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - } -} - -SMSC9220_EMAC::SMSC9220_EMAC() : receiver_thread(LINK_STATUS_THREAD_PRIORITY, - (uint32_t)LINK_STATUS_THREAD_STACKSIZE) -{ -} - -/** \brief Ethernet receive interrupt handler - * - * This function handles the receive interrupt. - */ -void SMSC9220_EMAC::rx_isr() -{ - receiver_thread.flags_set(FLAG_RX); -} - -/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming - * packet. - * - * \return a emac_mem_buf_t filled with the received packet - * (including MAC header) - */ -emac_mem_buf_t *SMSC9220_EMAC::low_level_input() -{ - emac_mem_buf_t *p = NULL; - uint32_t message_length = 0; - uint32_t received_bytes = 0; - - message_length = smsc9220_peek_next_packet_size(dev); - if (message_length == 0) { - return p; - } else { - /* The Ethernet controller cannot remove CRC from the end of the - * incoming packet, thus it should be taken into account when - * calculating the actual message length.*/ - message_length -= CRC_LENGTH_BYTES; - } - - p = _memory_manager->alloc_heap(SMSC9220_ETH_MAX_FRAME_SIZE, - SMSC9220_BUFF_ALIGNMENT); - - if (p != NULL) { - _RXLockMutex.lock(); - received_bytes = smsc9220_receive_by_chunks(dev, - (char*)_memory_manager->get_ptr(p), - _memory_manager->get_len(p)); - if(received_bytes == 0){ - _memory_manager->free(p); - p = nullptr; - } else { - _memory_manager->set_len(p, received_bytes); - } - _RXLockMutex.unlock(); - } - - return p; -} - -/** \brief Receiver thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] params pointer to the interface data - */ -void SMSC9220_EMAC::receiver_thread_function(void* params) -{ - struct SMSC9220_EMAC *smsc9220_enet = static_cast(params); - - while(1) { - uint32_t flags = ThisThread::flags_wait_any(FLAG_RX); - - if (flags & FLAG_RX) { - smsc9220_enet->packet_rx(); - } - } -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the Network Stack. - */ -void SMSC9220_EMAC::packet_rx() -{ - emac_mem_buf_t *p; - p = low_level_input(); - if(p != NULL) { - _emac_link_input_cb(p); - } - smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); -} - -bool SMSC9220_EMAC::link_out(emac_mem_buf_t *buf) -{ - if(buf == NULL) { - return false; - } else { - uint32_t buffer_chain_length = 0; - enum smsc9220_error_t error = SMSC9220_ERROR_NONE; - /* If buffer is chained or not aligned then - * make a contiguous aligned copy of it */ - if (_memory_manager->get_next(buf) || - reinterpret_cast(_memory_manager->get_ptr(buf)) % - SMSC9220_BUFF_ALIGNMENT) { - emac_mem_buf_t *copy_buf; - copy_buf = _memory_manager->alloc_heap( - _memory_manager->get_total_len(buf), - SMSC9220_BUFF_ALIGNMENT); - if (NULL == copy_buf) { - _memory_manager->free(buf); - return false; - } - - /* Copy to new buffer and free original */ - _memory_manager->copy(copy_buf, buf); - _memory_manager->free(buf); - buf = copy_buf; - } - - buffer_chain_length = _memory_manager->get_total_len(buf); - - _TXLockMutex.lock(); - error = smsc9220_send_by_chunks(dev, - buffer_chain_length, - true, - (const char*)_memory_manager->get_ptr(buf), - _memory_manager->get_len(buf)); - _memory_manager->free(buf); - _TXLockMutex.unlock(); - return (error == SMSC9220_ERROR_NONE); - } -} - -void SMSC9220_EMAC::link_status_task() -{ - uint32_t phy_basic_status_reg_value = 0; - bool current_link_status_up = false; - - /* Get current status */ - smsc9220_phy_regread(dev, SMSC9220_PHY_REG_OFFSET_BSTATUS, - &phy_basic_status_reg_value); - - current_link_status_up = (bool)(phy_basic_status_reg_value & - (1ul << (PHY_REG_BSTATUS_LINK_STATUS_INDEX))); - - /* Compare with the previous state */ - if (current_link_status_up != _prev_link_status_up) { - _emac_link_state_cb(current_link_status_up); - _prev_link_status_up = current_link_status_up; - } - -} - -bool SMSC9220_EMAC::power_up() -{ - board_emac_pointer = this; - receiver_thread.start(callback(&SMSC9220_EMAC::receiver_thread_function, - this)); - - /* Initialize the hardware */ - enum smsc9220_error_t init_successful = smsc9220_init(dev, &ThisThread::sleep_for); - if (init_successful != SMSC9220_ERROR_NONE) { - return false; - } - - /* Init FIFO level interrupts: use Rx status level irq to trigger - * interrupts for any non-processed packets, while Tx is not irq driven */ - smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); - smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN); - smsc9220_set_fifo_level_irq(dev, SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS, - SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX); - - /* Enable Ethernet interrupts in NVIC */ - NVIC_EnableIRQ(ETHERNET_IRQn); - smsc9220_enable_interrupt(dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL); - - /* Trigger thread to deal with any RX packets that arrived - * before receiver_thread was started */ - rx_isr(); - _prev_link_status_up = PHY_STATE_LINK_DOWN; - mbed::mbed_event_queue()->call(mbed::callback(this, - &SMSC9220_EMAC::link_status_task)); - - /* Allow the Link Status task to detect the initial link state */ - ThisThread::sleep_for(10); - _link_status_task_handle = mbed::mbed_event_queue()->call_every( - LINK_STATUS_TASK_PERIOD_MS, - mbed::callback(this, - &SMSC9220_EMAC::link_status_task)); - - return true; -} - -uint32_t SMSC9220_EMAC::get_mtu_size() const -{ - return SMSC9220_ETH_MTU_SIZE; -} - -uint32_t SMSC9220_EMAC::get_align_preference() const -{ - return SMSC9220_BUFF_ALIGNMENT; -} - -void SMSC9220_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, SMSC9220_ETH_IF_NAME, (size < sizeof(SMSC9220_ETH_IF_NAME)) ? - size : sizeof(SMSC9220_ETH_IF_NAME)); -} - -uint8_t SMSC9220_EMAC::get_hwaddr_size() const -{ - return SMSC9220_HWADDR_SIZE; -} - -bool SMSC9220_EMAC::get_hwaddr(uint8_t *addr) const -{ - if(smsc9220_read_mac_address(dev, (char*)addr) == SMSC9220_ERROR_NONE) { - return true; - } else { - return false; - } -} - -void SMSC9220_EMAC::set_hwaddr(const uint8_t *addr) -{ - if (!addr) { - return; - } - - memcpy(_hwaddr, addr, sizeof _hwaddr); - uint32_t mac_low = 0; - uint32_t mac_high = 0; - - /* Using local variables to make sure the right alignment is used */ - memcpy((void*)&mac_low, (void*)addr, 4); - memcpy((void*)&mac_high, (void*)(addr+4), 2); - - if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRL, mac_low)) { - return; - } - if (smsc9220_mac_regwrite(dev, SMSC9220_MAC_REG_OFFSET_ADDRH, mac_high)) { - return; - } -} - -void SMSC9220_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - _emac_link_input_cb = input_cb; -} - -void SMSC9220_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - _emac_link_state_cb = state_cb; -} - -void SMSC9220_EMAC::add_multicast_group(const uint8_t *addr) -{ - // No action for now -} - -void SMSC9220_EMAC::remove_multicast_group(const uint8_t *addr) -{ - // No action for now -} - -void SMSC9220_EMAC::set_all_multicast(bool all) -{ - // No action for now -} - -void SMSC9220_EMAC::power_down() -{ - // No action for now -} - -void SMSC9220_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - _memory_manager = &mem_mngr; -} - - -SMSC9220_EMAC &SMSC9220_EMAC::get_instance() { - static SMSC9220_EMAC emac; - return emac; -} - -/* Weak so a module can override */ -MBED_WEAK EMAC &EMAC::get_default_instance() { - return SMSC9220_EMAC::get_instance(); -} diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h deleted file mode 100644 index 58762d4..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2018 Arm Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SMSC9220_EMAC_H_ -#define SMSC9220_EMAC_H_ - -#include "EMAC.h" -#include "mbed.h" -#include "rtos/Mutex.h" - -#include "smsc9220_emac_config.h" - -class SMSC9220_EMAC : public EMAC { -public: - SMSC9220_EMAC(); - - static SMSC9220_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may - * or may not align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct - * size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own - * HW address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is - * provided the stack would normally use that, but it could be overridden, - * eg for test purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that - * interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given - * interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - void rx_isr(); - - static const struct smsc9220_eth_dev_t *dev; - -private: - void packet_rx(); - void link_status_task(); - bool low_level_init_successful(); - emac_mem_buf_t *low_level_input(); - static void receiver_thread_function(void* params); - - rtos::Mutex _TXLockMutex; - rtos::Mutex _RXLockMutex; - bool _prev_link_status_up; - int _link_status_task_handle; - uint8_t _hwaddr[SMSC9220_HWADDR_SIZE]; - - Thread receiver_thread; - EMACMemoryManager *_memory_manager; - emac_link_input_cb_t _emac_link_input_cb; - emac_link_state_change_cb_t _emac_link_state_cb; - -}; - -#endif /* SMSC9220_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h b/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h deleted file mode 100644 index 93d73f4..0000000 --- a/features/netsocket/emac-drivers/TARGET_ARM_SSG/COMPONENT_SMSC9220/smsc9220_emac_config.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SMSC9220_EMAC_CONFIG_H -#define SMSC9220_EMAC_CONFIG_H - -#include "cmsis_os.h" - -#define SMSC9220_HWADDR_SIZE 6U -#define SMSC9220_BUFF_ALIGNMENT 4U - -/* - * Maximum Transfer Unit - * The IEEE 802.3 specification limits the data portion of the 802.3 frame - * to a minimum of 46 and a maximum of 1522 bytes, this is on L2 level. - */ -#define SMSC9220_ETH_MTU_SIZE 1500U -#define SMSC9220_ETH_IF_NAME "smsc9220" -#define SMSC9220_ETH_MAX_FRAME_SIZE 1522U - -/** \brief Defines for receiver thread */ -#define FLAG_RX 1U -#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal) -#define LINK_STATUS_THREAD_STACKSIZE 512U -#define LINK_STATUS_TASK_PERIOD_MS 200U -#define PHY_STATE_LINK_DOWN false -#define PHY_STATE_LINK_UP true -#define CRC_LENGTH_BYTES 4U - -#endif /* SMSC9220_EMAC_CONFIG_H */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp deleted file mode 100644 index 1fefdee..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2018-2020 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "SclSTAInterface.h" -#include "nsapi.h" -#include "lwipopts.h" -#include "lwip/etharp.h" -#include "lwip/ethip6.h" -#include "rtos.h" -#include "scl_emac.h" -#include "scl_ipc.h" -#include "mbed_wait_api.h" - - -/** @file - * Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects - */ -#define MIN_SSID_LENGTH (0) -#define MIN_PASSWORD_LENGTH (0) - -struct scl_tx_net_credentials { - nsapi_security_t network_security_type; - int ssid_len; - int pass_len; - const char *network_ssid; - const char *network_passphrase; -} scl_tx_network_credentials; - -network_params_t network_parameter; - -int scl_toerror(scl_result_t res) -{ - switch (res) { - case SCL_SUCCESS: - return NSAPI_ERROR_OK; - case SCL_UNSUPPORTED: - return NSAPI_ERROR_UNSUPPORTED; - case SCL_BADARG: - return NSAPI_ERROR_PARAMETER; - case SCL_INVALID_JOIN_STATUS: - return NSAPI_ERROR_NO_CONNECTION; - case SCL_BUFFER_UNAVAILABLE_PERMANENT: - case SCL_BUFFER_UNAVAILABLE_TEMPORARY: - case SCL_RX_BUFFER_ALLOC_FAIL: - case SCL_BUFFER_ALLOC_FAIL: - case SCL_MALLOC_FAILURE: - return NSAPI_ERROR_NO_MEMORY; - case SCL_ACCESS_POINT_NOT_FOUND: - case SCL_NETWORK_NOT_FOUND: - return NSAPI_ERROR_NO_SSID; - case SCL_NOT_AUTHENTICATED: - case SCL_INVALID_KEY: - case SCL_NOT_KEYED: - return NSAPI_ERROR_AUTH_FAILURE; - case SCL_PENDING: - case SCL_JOIN_IN_PROGRESS: - return NSAPI_ERROR_IN_PROGRESS; - case SCL_CONNECTION_LOST: - return NSAPI_ERROR_CONNECTION_LOST; - case SCL_TIMEOUT: - case SCL_EAPOL_KEY_PACKET_M1_TIMEOUT: - case SCL_EAPOL_KEY_PACKET_M3_TIMEOUT: - case SCL_EAPOL_KEY_PACKET_G1_TIMEOUT: - return NSAPI_ERROR_CONNECTION_TIMEOUT; - default: - return -res; - } -} - -nsapi_security_t scl_tosecurity(scl_security_t sec) -{ - switch (sec) { - case SCL_SECURITY_OPEN: - return NSAPI_SECURITY_NONE; - case SCL_SECURITY_WEP_PSK: - case SCL_SECURITY_WEP_SHARED: - return NSAPI_SECURITY_WEP; - case SCL_SECURITY_WPA_TKIP_PSK: - case SCL_SECURITY_WPA_TKIP_ENT: - return NSAPI_SECURITY_WPA; - case SCL_SECURITY_WPA2_MIXED_PSK: - return NSAPI_SECURITY_WPA_WPA2; - case SCL_SECURITY_WPA2_AES_PSK: - case SCL_SECURITY_WPA2_AES_ENT: - case SCL_SECURITY_WPA2_FBT_PSK: - case SCL_SECURITY_WPA2_FBT_ENT: - return NSAPI_SECURITY_WPA2; - default: - return NSAPI_SECURITY_UNKNOWN; - } -} - -scl_security_t scl_fromsecurity(nsapi_security_t sec) -{ - switch (sec) { - case NSAPI_SECURITY_NONE: - return SCL_SECURITY_OPEN; - case NSAPI_SECURITY_WEP: - return SCL_SECURITY_WEP_PSK; - case NSAPI_SECURITY_WPA: - return SCL_SECURITY_WPA_MIXED_PSK; - case NSAPI_SECURITY_WPA2: - return SCL_SECURITY_WPA2_AES_PSK; - case NSAPI_SECURITY_WPA_WPA2: - return SCL_SECURITY_WPA2_MIXED_PSK; - default: - return SCL_SECURITY_UNKNOWN; - } -} - -SclSTAInterface::SclSTAInterface(SCL_EMAC &emac, OnboardNetworkStack &stack) - : EMACInterface(emac, stack), - _ssid("\0"), - _pass("\0"), - _security(NSAPI_SECURITY_NONE), - _scl_emac(emac) -{ -} - -nsapi_error_t SclSTAInterface::connect(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel) -{ - int err = set_channel(channel); - if (err) { - return err; - } - - err = set_credentials(ssid, pass, security); - if (err) { - return err; - } - - return connect(); -} - -nsapi_error_t SclSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) -{ - if ((ssid == NULL) || - (strlen(ssid) == 0) || - (pass == NULL && (security != NSAPI_SECURITY_NONE)) || - (strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE)) || - (strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA || security == NSAPI_SECURITY_WPA_WPA2)) - ) { - return NSAPI_ERROR_PARAMETER; - } - - memset(_ssid, 0, sizeof(_ssid)); - strncpy(_ssid, ssid, sizeof(_ssid)); - - memset(_pass, 0, sizeof(_pass)); - strncpy(_pass, pass, sizeof(_pass)); - - _security = security; - - return NSAPI_ERROR_OK; -} - -nsapi_error_t SclSTAInterface::connect() -{ - - uint32_t delay_timeout = 0; - scl_result_t ret_val; - nsapi_error_t interface_status; - uint32_t connection_status = 0; - - scl_tx_network_credentials.network_ssid = _ssid; - if ((strlen(_ssid) < MAX_SSID_LENGTH) && (strlen(_ssid) > MIN_SSID_LENGTH)) { - scl_tx_network_credentials.ssid_len = strlen(_ssid); - } else { - return NSAPI_ERROR_PARAMETER; - } - scl_tx_network_credentials.network_passphrase = _pass; - if (((strlen(_pass) < MAX_PASSWORD_LENGTH) && (strlen(_pass) > MIN_PASSWORD_LENGTH)) || (_security == NSAPI_SECURITY_NONE)) { - scl_tx_network_credentials.pass_len = strlen(_pass); - } else { - return NSAPI_ERROR_PARAMETER; - } - scl_tx_network_credentials.network_security_type = _security; - - ret_val = scl_send_data(SCL_TX_CONNECT, (char *)&scl_tx_network_credentials, TIMER_DEFAULT_VALUE); - - if (ret_val == SCL_SUCCESS) { - SCL_LOG(("wifi provisioning in progress\r\n")); - } - - network_parameter.connection_status = NSAPI_STATUS_DISCONNECTED; - - - //Get the network parameter from NP - while ((network_parameter.connection_status != NSAPI_STATUS_GLOBAL_UP) && delay_timeout < NW_CONNECT_TIMEOUT) { - ret_val = scl_get_nw_parameters(&network_parameter); - wait_us(NW_DELAY_TIME_US); - delay_timeout++; - } - - if (delay_timeout >= NW_CONNECT_TIMEOUT || ret_val != SCL_SUCCESS) { - return NSAPI_ERROR_NO_CONNECTION; - } - - if (!_scl_emac.powered_up) { - _scl_emac.power_up(); - } - - if (!_interface) { - nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); - if (err != NSAPI_ERROR_OK) { - _interface = NULL; - return err; - } - _interface->attach(_connection_status_cb); - } - - if (!scl_wifi_is_ready_to_transceive()) { - scl_emac_wifi_link_state_changed(true); - } - - interface_status = _interface->bringup(false, - network_parameter.ip_address, - network_parameter.netmask, - network_parameter.gateway, - DEFAULT_STACK); - - if (interface_status == NSAPI_ERROR_OK) { - scl_send_data(SCL_TX_CONNECTION_STATUS, (char *)&connection_status, TIMER_DEFAULT_VALUE); - } - - return interface_status; -} - -void SclSTAInterface::wifi_on() -{ - if (!_scl_emac.powered_up) { - _scl_emac.power_up(); - } -} - -nsapi_error_t SclSTAInterface::disconnect() -{ - scl_result_t ret_val; - nsapi_error_t disconnect_status; - uint32_t delay_timeout = 0; - - ret_val = scl_send_data(SCL_TX_DISCONNECT, (char *)&disconnect_status, TIMER_DEFAULT_VALUE); - - if (ret_val == SCL_ERROR) { - return NSAPI_ERROR_TIMEOUT; - } - - if (!_interface) { - return NSAPI_ERROR_NO_CONNECTION; - } - - // block till disconnected from network - while ((network_parameter.connection_status != NSAPI_STATUS_DISCONNECTED) && delay_timeout < NW_DISCONNECT_TIMEOUT) { - ret_val = scl_get_nw_parameters(&network_parameter); - wait_us(NW_DELAY_TIME_US); - delay_timeout++; - } - - if (delay_timeout >= NW_DISCONNECT_TIMEOUT) { - return NSAPI_ERROR_TIMEOUT; - } - - // bring down - int err = _interface->bringdown(); - if (err) { - return err; - } - - scl_emac_wifi_link_state_changed(false); - - return NSAPI_ERROR_OK; -} - -int SclSTAInterface::scan(WiFiAccessPoint *res, unsigned count) -{ - /* To Do */ - return NSAPI_ERROR_UNSUPPORTED; -} - -int8_t SclSTAInterface::get_rssi() -{ - int32_t rssi; - scl_result_t res; - - if (!_scl_emac.powered_up) { - _scl_emac.power_up(); - } - - res = (scl_result_t) scl_wifi_get_rssi(&rssi); - if (res == SCL_ERROR) { - return SCL_ERROR; - } - - return (int8_t)rssi; -} - -int SclSTAInterface::is_interface_connected(void) -{ - if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) { - return SCL_SUCCESS; - } else { - return SCL_CONNECTION_LOST; - } -} - -int SclSTAInterface::get_bssid(uint8_t *bssid) -{ - scl_mac_t ap_mac; - scl_result_t res = SCL_SUCCESS; - - if (bssid == NULL) { - return SCL_BADARG; - } - - memset(&ap_mac, 0, sizeof(ap_mac)); - if (scl_wifi_is_ready_to_transceive() == SCL_SUCCESS) { - res = (scl_result_t) scl_wifi_get_bssid(&ap_mac); - if (res == SCL_SUCCESS) { - memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet)); - } - } else { - return SCL_CONNECTION_LOST; - } - return res; -} - -int SclSTAInterface::wifi_set_up(void) -{ - int res = SCL_SUCCESS; - res = scl_wifi_set_up(); - return res; -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h deleted file mode 100644 index 801a9a5..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/SclSTAInterface.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2018-2020 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SCL_STA_INTERFACE_H -#define SCL_STA_INTERFACE_H - - -/** @file - * Provides SCL interface functions to be used with WiFiInterface or NetworkInterface Objects - */ - -#include "netsocket/WiFiInterface.h" -#include "netsocket/EMACInterface.h" -#include "netsocket/OnboardNetworkStack.h" -#include "scl_emac.h" -#include "scl_wifi_api.h" -#include "scl_types.h" -#define MAX_SSID_LENGTH (33) /**< Maximum ssid length */ -#define MAX_PASSWORD_LENGTH (64) /**< Maximum password length */ - -/** SclSTAInterface class - * Implementation of the Network Stack for the SCL - */ -class SclSTAInterface : public WiFiInterface, public EMACInterface { -public: - - SclSTAInterface( - SCL_EMAC &emac = SCL_EMAC::get_instance(), - OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance()); - - /** Gets the current instance of the SclSTAInterface - * - * @return Pointer to the object of class SclSTAInterface. - */ - static SclSTAInterface *get_default_instance(); - - /** Turns on the Wi-Fi device - * - * @return void - */ - void wifi_on(); - - /** Starts the interface - * - * Attempts to connect to a Wi-Fi network. Requires ssid and passphrase to be set. - * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned. - * - * @return 0 on success, negative error code on failure. - */ - nsapi_error_t connect(); - - /** Starts the interface - * - * Attempts to connect to a Wi-Fi network. - * - * @param ssid Name of the network to connect to. - * @param pass Security passphrase to connect to the network. - * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE). - * @param channel This parameter is not supported, setting it to a value other than 0 will result in NSAPI_ERROR_UNSUPPORTED. - * @return 0 on success, negative error code on failure. - */ - nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0); - - /** Disconnects the interface - * - * @return 0 on success, negative error code on failure. - */ - nsapi_error_t disconnect(); - - /** Set the Wi-Fi network credentials - * - * @param ssid Name of the network to connect to. - * @param pass Security passphrase to connect to the network. - * @param security Type of encryption for connection. - * (defaults to NSAPI_SECURITY_NONE) - * @return 0 on success, negative error code on failure. - */ - nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE); - - /** Sets the Wi-Fi network channel - NOT SUPPORTED - * - * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED. - * - * @param channel Channel on which the connection is to be made (Default: 0). - * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED. - */ - nsapi_error_t set_channel(uint8_t channel) - { - if (channel != 0) { - return NSAPI_ERROR_UNSUPPORTED; - } - return 0; - } - - /** Set blocking status of interface. - * Nonblocking mode is not supported. - * - * @param blocking True if connect is blocking - * @return 0 on success, negative error code on failure - */ - nsapi_error_t set_blocking(bool blocking) - { - if (blocking) { - _blocking = blocking; - return NSAPI_ERROR_OK; - } else { - return NSAPI_ERROR_UNSUPPORTED; - } - } - /** Gets the current radio signal strength for active connection - * - * @return Connection strength in dBm (negative value). - */ - int8_t get_rssi(); - - /** Scans for available networks - NOT SUPPORTED - * - * @return NSAPI_ERROR_UNSUPPORTED - */ - int scan(WiFiAccessPoint *res, unsigned count); - - /** This function is used to indicate if the device is connected to the network. - * - * @return SCL_SUCCESS if device is connected. - */ - int is_interface_connected(); - - /** Gets the BSSID (MAC address of device connected to). - * - * @param bssid Pointer to the BSSID value. - * @return SCL_SUCCESS if BSSID is obtained successfully. - * @return SCL_BADARG if input parameter is NULL. - * @return SCL_ERROR if unable to fetch BSSID. - */ - int get_bssid(uint8_t *bssid); - - /** This function is used to set up the Wi-Fi interface. - * This function should be used after the wifi_on. - * - * @return SCL_SUCCESS if the Wi-Fi interface is set up successfully. - */ - int wifi_set_up(void); - -private: - - char _ssid[MAX_SSID_LENGTH]; /**< The longest possible name (defined in 802.11) +1 for the \0 */ - char _pass[MAX_PASSWORD_LENGTH]; /**< The longest allowed passphrase + 1 */ - nsapi_security_t _security; /**< Security type */ - SCL_EMAC &_scl_emac; /**< SCL_EMAC object */ -}; -#endif /* ifndef SCL_STA_INTERFACE_H */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp deleted file mode 100644 index 59cb5ef..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/default_wifi_interface.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2018-2020 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SclSTAInterface.h" - -/** @file -* Provides function definition to override get_target_default_intance of WiFiInterface and NetworkInterface classes -*/ - -/** - * Returns the WiFiInterface Object - * This function can be called using WiFiInterface or NetworkInterface objects - * - * @return pointer to WiFiInterface object. - */ - -WiFiInterface *WiFiInterface::get_target_default_instance() -{ - static SclSTAInterface wifi; - return &wifi; -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp deleted file mode 100644 index 24c3408..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2018-2020 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" -#include "scl_emac.h" -#include "lwip/etharp.h" -#include "lwip/ethip6.h" -#include "mbed_shared_queues.h" -#include "scl_buffer_api.h" -#include "cy_result.h" -#include "cy_pdl.h" -#include "scl_ipc.h" - -/** @file - * Provides EMAC interface functions to be used with the SCL_EMAC object - */ - -SCL_EMAC::SCL_EMAC(scl_interface_role_t role) - : interface_type(role) -{ -} - -SCL_EMAC::SCL_EMAC() - : interface_type(SCL_STA_ROLE) -{ -} - -SCL_EMAC &SCL_EMAC::get_instance() -{ - return get_instance(SCL_STA_ROLE); -} - -SCL_EMAC &SCL_EMAC::get_instance(scl_interface_role_t role) -{ - static SCL_EMAC emac_sta(SCL_STA_ROLE); - static SCL_EMAC emac_ap(SCL_AP_ROLE); - return role == SCL_AP_ROLE ? emac_ap : emac_sta; -} - -uint32_t SCL_EMAC::get_mtu_size() const -{ - return SCL_PAYLOAD_MTU; -} - -uint32_t SCL_EMAC::get_align_preference() const -{ - return 0; -} - -void SCL_EMAC::add_multicast_group(const uint8_t *addr) -{ - memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet)); - scl_wifi_register_multicast_address(&multicast_addr); -} - -void SCL_EMAC::remove_multicast_group(const uint8_t *address) -{ - /* To Do */ -} -void SCL_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void SCL_EMAC::power_down() -{ - /* No-op at this stage */ -} - -bool SCL_EMAC::power_up() -{ - if (!powered_up) { -#ifdef MBED_TEST_MODE - scl_init(); -#endif - if (!scl_wifi_on()) { - SCL_LOG(("WiFi failed to turn on\r\n")); - return false; - } - powered_up = true; - if (link_state && emac_link_state_cb) { - emac_link_state_cb(link_state); - } - } - return true; -} - -bool SCL_EMAC::get_hwaddr(uint8_t *addr) const -{ - scl_mac_t mac; - scl_result_t res = scl_wifi_get_mac_address(&mac); - if (res == SCL_SUCCESS) { - memcpy(addr, mac.octet, sizeof(mac.octet)); - return true; - } else { - SCL_LOG(("Unable to get MAC address\r\n")); - return false; - } -} - -void SCL_EMAC::set_hwaddr(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -uint8_t SCL_EMAC::get_hwaddr_size() const -{ - scl_mac_t mac; - return sizeof(mac.octet); -} - -void SCL_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void SCL_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void SCL_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -bool SCL_EMAC::link_out(emac_mem_buf_t *buf) -{ - scl_result_t retval; - scl_tx_buf_t scl_tx_data; - scl_tx_data.size = memory_manager->get_total_len(buf); - scl_tx_data.buffer = buf; - if (buf == NULL) { - return false; - } - - retval = scl_network_send_ethernet_data(scl_tx_data); //Buffer is copied on Network Processor - if (retval != SCL_SUCCESS) { - return false; - } - memory_manager->free(buf); - return true; -} - -void SCL_EMAC::get_ifname(char *name, uint8_t size) const -{ - if (name != NULL) { - memcpy(name, "scl", size); - } -} - -void SCL_EMAC::set_activity_cb(mbed::Callback cb) -{ - activity_cb = cb; -} - -extern "C" -{ - void scl_network_process_ethernet_data(scl_buffer_t buffer) - { - emac_mem_buf_t *mem_buf = NULL; - - SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE); - - if (!emac.powered_up && !emac.emac_link_input_cb) { - scl_buffer_release(buffer, SCL_NETWORK_RX); - return; - } - mem_buf = buffer; - if (emac.activity_cb) { - emac.activity_cb(false); - } - emac.emac_link_input_cb(mem_buf); - } - - void scl_emac_wifi_link_state_changed(bool state_up) - { - SCL_EMAC &emac = SCL_EMAC::get_instance(SCL_STA_ROLE); - - emac.link_state = state_up; - if (emac.emac_link_state_cb) { - emac.emac_link_state_cb(state_up); - } - } -} // extern "C" - - diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h deleted file mode 100644 index e6e3ecd..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_SCL/interface/scl_emac.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2018-2020 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SCL_EMAC_H_ -#define SCL_EMAC_H_ - -/** @file - * Provides EMAC interface functions to be used with the SCL_EMAC object - * - */ -#include "EMAC.h" -#include "EMACInterface.h" -#include "WiFiInterface.h" -#include "scl_common.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" -#include "scl_wifi_api.h" -class SCL_EMAC : public EMAC { -public: - SCL_EMAC(); - SCL_EMAC(scl_interface_role_t itype); - - /** - * Get the EMAC instance - * - * @return Reference to SCL_EMAC object. - */ - static SCL_EMAC &get_instance(); - - /** - * Get the EMAC instance - * - * @param role Interface type. - * - * @return Reference to SCL_EMAC object. - */ - static SCL_EMAC &get_instance(scl_interface_role_t role); - - /** - * Returns the maximum transmission unit - * - * @return MTU in bytes. - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets the memory buffer alignment preference - * - * Gets the preferred memory buffer alignment of the EMAC device. IP stack may or may not - * align with the link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes. - */ - virtual uint32_t get_align_preference() const; - - /** - * Returns the interface name - * - * @param name Pointer to the location where the name should be written. - * @param size Maximum number of characters to copy. - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns the size of the underlying interface HW address size. - * - * @return HW address size in bytes. - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Returns the interface supplied HW address - * Copies the HW address to the provided memory - * @param addr HW address of the underlying interface. It must be of correct size. See @a get_hwaddr_size. - * @return True if HW address is available. - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for the interface - * - * Provided address must be of correct size. See @a get_hwaddr_size. - * - * Called to set the MAC address to be used - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * This cannot be called from an interrupt context. - * - * @param buf Packet to be sent. - * @return True if the packet was sent successfully. False otherwise. - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success. False in case of an error. - */ - virtual bool power_up(); - - /** - * De-initializes the HW - */ - virtual void power_down(); - - /** - * Sets a callback that is called for packets received for a given interface - * - * @param input_cb Function to be registered as a callback. - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that is called on changes in the link status for a given interface - * - * @param state_cb Function to be registered as a callback. - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Adds a device to a multicast group - * - * @param address A multicast group hardware address. - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Removes a device from a multicast group - * - * @param address A multicast group hardware address. - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Requests reception of all multicast packets - * - * @param all True to receive all multicasts. - * False to receive only multicasts addressed to specified groups. - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager. - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - /** Sets callback to receive EMAC activity events - * - * @param activity_cb The callback for activity events. - */ - virtual void set_activity_cb(mbed::Callback activity_cb); - - emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb = NULL; /**< Callback for network connection status */ - EMACMemoryManager *memory_manager; /**< Pointer to hold memory manager object */ - bool powered_up = false; /**< Flag for Wi-Fi power on status */ - bool link_state = false; /**< Flag for network connection status */ - scl_interface_role_t interface_type; /**< Type of the interface */ - scl_mac_t multicast_addr; /**< Multicast address */ - mbed::Callback activity_cb; /**< Callback for activity on network */ - -}; -/** Sends the change in network connection state to network stack -* -* @param state_up Connection status. -*/ -extern "C" void scl_emac_wifi_link_state_changed(bool state_up); - -#endif /* SCL_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp deleted file mode 100644 index ca84423..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "CyDhcpServer.h" -#include "cy_utils.h" -#include "Callback.h" -#include "def.h" -#include "whd_types.h" - -#ifdef DHCP_EXTENSIVE_DEBUG -extern "C" void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title); -#endif - -/* UDP port numbers for DHCP server and client */ -#define IP_PORT_DHCP_SERVER (67) -#define IP_PORT_DHCP_CLIENT (68) - -/* BOOTP operations */ -#define BOOTP_OP_REQUEST (1) -#define BOOTP_OP_REPLY (2) - -/* DCHP message types */ -#define DHCP_MSG_TYPE_DISCOVER (1) -#define DHCP_MSG_TYPE_OFFER (2) -#define DHCP_MSG_TYPE_REQUEST (3) -#define DHCP_MSG_TYPE_DECLINE (4) -#define DHCP_MSG_TYPE_ACK (5) -#define DHCP_MSG_TYPE_NACK (6) -#define DHCP_MSG_TYPE_RELEASE (7) -#define DHCP_MSG_TYPE_INFORM (8) -#define DHCP_MSG_TYPE_INVALID (255) - -#define DHCP_MSG_MAGIC_COOKIE (0x63825363) - -#define DHCP_STACK_SIZE (8*1024) - -/********************* Options manipulation functions ***********************************/ -static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype) -{ - if (index + sizeof(dhcp_packet_t) - 1 + 1 >= DHCP_PACKET_SIZE) { - printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); - return; - } - - dhcp->Options[index++] = optype; - - return; -} - -static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t value) -{ - if (index + sizeof(dhcp_packet_t) - 1 + 3 >= DHCP_PACKET_SIZE) { - printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); - return; - } - - dhcp->Options[index++] = optype; - dhcp->Options[index++] = 0x01; - dhcp->Options[index++] = value; - - return; -} - -static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint16_t value) -{ - if (index + sizeof(dhcp_packet_t) - 1 + 4 >= DHCP_PACKET_SIZE) { - printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); - return; - } - - dhcp->Options[index++] = optype; - dhcp->Options[index++] = 0x02; - dhcp->Options[index++] = static_cast((value >> 0) & 0xFF); - dhcp->Options[index++] = static_cast((value >> 8) & 0xFF); - - return; -} - -static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint32_t value) -{ - if (index + sizeof(dhcp_packet_t) - 1 + 6 >= DHCP_PACKET_SIZE) { - printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); - return; - } - - dhcp->Options[index++] = optype; - dhcp->Options[index++] = 0x04; - dhcp->Options[index++] = static_cast((value >> 0) & 0xFF); - dhcp->Options[index++] = static_cast((value >> 8) & 0xFF); - dhcp->Options[index++] = static_cast((value >> 16) & 0xFF); - dhcp->Options[index++] = static_cast((value >> 24) & 0xFF); - - return; -} - -static void addOption(dhcp_packet_t *dhcp, uint32_t &index, uint8_t optype, uint8_t *value, uint32_t size) -{ - if (index + sizeof(dhcp_packet_t) - 1 + 2 + size >= DHCP_PACKET_SIZE) { - printf("DHCP ERROR: Option index %d (Optype: %d) written to exceeds size of the packet", (int)index, (int)optype); - return; - } - - dhcp->Options[index++] = optype; - dhcp->Options[index++] = size; - memcpy(&dhcp->Options[index], value, size); - index += size; - - return; -} - -static const uint8_t *findOption(const dhcp_packet_t *request, uint8_t option_num) -{ - const uint8_t *option_ptr = request->Options; - while ((option_ptr[0] != DHCP_END_OPTION_CODE) && - (option_ptr[0] != option_num) && - (option_ptr < ((const uint8_t *)request) + DHCP_PACKET_SIZE)) { - option_ptr += option_ptr[1] + 2; - } - - /* Was the option found? */ - if (option_ptr[0] == option_num) { - return &option_ptr[2]; - } - return NULL; -} - -static void addCommonOptions(dhcp_packet_t *dhcp, uint32_t &index, const uint32_t server_addr, const uint32_t netmask) -{ - /* Prepare the Web proxy auto discovery URL */ - char wpad_sample_url[] = "http://xxx.xxx.xxx.xxx/wpad.dat"; - char ip_str[16]; - ipv4_to_string(ip_str, htonl(server_addr)); - memcpy(&wpad_sample_url[7], &ip_str[0], 15); - - /* Server identifier */ - addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, server_addr); - /* Lease Time */ - addOption(dhcp, index, DHCP_LEASETIME_OPTION_CODE, static_cast(0x00015180)); - /* Subnet Mask */ - addOption(dhcp, index, DHCP_SUBNETMASK_OPTION_CODE, htonl(netmask)); - /* Web proxy auto discovery URL */ - addOption(dhcp, index, DHCP_WPAD_OPTION_CODE, (uint8_t *)&wpad_sample_url[0], strlen(wpad_sample_url)); - /* Router (gateway) */ - addOption(dhcp, index, DHCP_ROUTER_OPTION_CODE, htonl(server_addr)); - /* DNS server */ - addOption(dhcp, index, DHCP_DNS_SERVER_OPTION_CODE, htonl(server_addr)); - /* Interface MTU */ - addOption(dhcp, index, DHCP_MTU_OPTION_CODE, static_cast(WHD_PAYLOAD_MTU)); -} - -static void sendPacket(UDPSocket *socket, dhcp_packet_t *dhcp, uint32_t size) -{ - nsapi_size_or_error_t err; - uint32_t broadcast_ip = 0xFFFFFFFF; - char string_addr[16]; - ipv4_to_string(string_addr, htonl(broadcast_ip)); - SocketAddress sock_addr(string_addr, IP_PORT_DHCP_CLIENT); - - err = socket->sendto(sock_addr, reinterpret_cast(dhcp), size); - if (err < 0) { - printf("DHCP ERROR: Packet send failure with error %d.", err); - } else if (err != (int)size) { - printf("DHCP ERROR: Could not send entire packet. Only %d bytes were sent.", err); - } -} - -/********************* Cache utility functions ***********************************/ -void CyDhcpServer::setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr) -{ - uint32_t a; - uint32_t first_empty_slot; - uint32_t cached_slot; - char empty_cache[NSAPI_IPv6_SIZE] = ""; - - /* Search for empty slot in cache */ - for (a = 0, first_empty_slot = DHCP_IP_ADDRESS_CACHE_MAX, cached_slot = DHCP_IP_ADDRESS_CACHE_MAX; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { - /* Check for matching MAC address */ - if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { - /* Cached device found */ - cached_slot = a; - break; - } else if (first_empty_slot == DHCP_IP_ADDRESS_CACHE_MAX && memcmp(&_mac_addr_cache[a], &empty_cache, sizeof(cy_mac_addr_t)) == 0) { - /* Device not found in cache. Return the first empty slot */ - first_empty_slot = a; - } - } - - if (cached_slot != DHCP_IP_ADDRESS_CACHE_MAX) { - /* Update IP address of cached device */ - _ip_addr_cache[cached_slot] = addr; - } else if (first_empty_slot != DHCP_IP_ADDRESS_CACHE_MAX) { - /* Add device to the first empty slot */ - _mac_addr_cache[first_empty_slot] = mac_id; - _ip_addr_cache[first_empty_slot] = addr; - } else { - /* Cache is full. Add device to slot 0 */ - _mac_addr_cache[0] = mac_id; - _ip_addr_cache [0] = addr; - } -} - -bool CyDhcpServer::lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr) -{ - /* Check whether device is already cached */ - for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { - if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { - addr = _ip_addr_cache[a]; - return true; - } - } - return false; -} - -void CyDhcpServer::freeAddress(const cy_mac_addr_t &mac_id) -{ - /* Check whether device is already cached */ - for (uint32_t a = 0; a < DHCP_IP_ADDRESS_CACHE_MAX; a++) { - if (memcmp(&_mac_addr_cache[a], &mac_id, sizeof(mac_id)) == 0) { - memset(&_mac_addr_cache[a], 0, sizeof(_mac_addr_cache[a])); - memset(&_ip_addr_cache[a], 0, sizeof(_ip_addr_cache[a])); - } - } -} - -void CyDhcpServer::handleDiscover(dhcp_packet_t *dhcp) -{ -#ifdef DHCP_EXTENSIVE_DEBUG - dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP DISCOVER RECEIVED"); -#endif - - uint32_t index; - cy_mac_addr_t client_mac; - cy_ip_addr_t client_ip; - - memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac)); - if (!lookupAddress(client_mac, client_ip)) { - client_ip = _available_addr; - } - - memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy)); - memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3); - - dhcp->Opcode = BOOTP_OP_REPLY; - dhcp->YourIpAddr = htonl(client_ip.addrv4.addr); - dhcp->MagicCookie = htonl(static_cast(DHCP_MSG_MAGIC_COOKIE)); - - /* Add options */ - index = 0; - addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_OFFER)); - addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr); - addOption(dhcp, index, static_cast(DHCP_END_OPTION_CODE)); - - uint32_t size = sizeof(dhcp_packet_t) + index - 1; - CY_ASSERT(size <= DHCP_PACKET_SIZE); - -#ifdef DHCP_EXTENSIVE_DEBUG - dhcp_server_print_header_info(dhcp, size, "\n\nDHCP OFFER SENT"); -#endif - sendPacket(&_socket, dhcp, size); -} - -void CyDhcpServer::handleRequest(dhcp_packet_t *dhcp) -{ -#ifdef DHCP_EXTENSIVE_DEBUG - dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST RECEIVED"); -#endif - - cy_mac_addr_t client_mac; - cy_ip_addr_t client_ip; - cy_ip_addr_t req_ip; - bool increment = false; - uint32_t index; - - /* Check that the REQUEST is for this server */ - uint32_t *server_id_req = (uint32_t *)findOption(dhcp, DHCP_SERVER_IDENTIFIER_OPTION_CODE); - if ((server_id_req == NULL) || ((server_id_req != NULL) && (_server_addr.addrv4.addr != *server_id_req))) { - return; /* Server ID was not found or does not match local IP address */ - } - - /* Locate the requested address in the options and keep requested address */ - req_ip.addrv4.addr = ntohl(*(uint32_t *)findOption(dhcp, DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE)); - - memcpy(&client_mac, dhcp->ClientHwAddr, sizeof(client_mac)); - if (!lookupAddress(client_mac, client_ip)) { - client_ip = _available_addr; - increment = true; - } - - memset(&dhcp->Legacy, 0, sizeof(dhcp->Legacy)); - memset(&dhcp->Options[0], 0, DHCP_PACKET_SIZE - sizeof(dhcp_packet_t) + 3); - - dhcp->Opcode = BOOTP_OP_REPLY; - dhcp->MagicCookie = htonl(static_cast(DHCP_MSG_MAGIC_COOKIE)); - - index = 0; - /* Check if the requested IP address matches one we have assigned */ - if (req_ip.addrv4.addr != client_ip.addrv4.addr) { - /* Request is not for the assigned IP - force client to take next available IP by sending NAK */ - addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_NACK)); - addOption(dhcp, index, DHCP_SERVER_IDENTIFIER_OPTION_CODE, _server_addr.addrv4.addr); - printf("\n\nDHCP_THREAD: %d REQUEST NAK\n", __LINE__); - } else { - dhcp->YourIpAddr = htonl(client_ip.addrv4.addr); - - addOption(dhcp, index, DHCP_MESSAGETYPE_OPTION_CODE, static_cast(DHCP_MSG_TYPE_ACK)); - addCommonOptions(dhcp, index, _server_addr.addrv4.addr, _netmask.addrv4.addr); - - if (increment) { - uint32_t ip_mask = ~(_netmask.addrv4.addr); - uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr; - do { - _available_addr.addrv4.addr = subnet | ((_available_addr.addrv4.addr + 1) & ip_mask); - } while (_available_addr.addrv4.addr == _server_addr.addrv4.addr); - } - setAddress(client_mac, client_ip); - } - addOption(dhcp, index, static_cast(DHCP_END_OPTION_CODE)); - - uint32_t size = sizeof(dhcp_packet_t) + index - 1; - CY_ASSERT(size <= DHCP_PACKET_SIZE); - -#ifdef DHCP_EXTENSIVE_DEBUG - dhcp_server_print_header_info(dhcp, DHCP_PACKET_SIZE, "\n\nDHCP REQUEST REPLY SENT"); -#endif - sendPacket(&_socket, dhcp, size); -} - -void CyDhcpServer::runServer(void) -{ - nsapi_size_or_error_t err_or_size; - - _running = true; - - /* Create receive DHCP socket */ - _socket.open(_nstack); - char iface_name[8] = {0}; - _niface->get_interface_name(iface_name); - _socket.setsockopt(NSAPI_SOCKET, NSAPI_BIND_TO_DEVICE, iface_name, strlen(iface_name)); - _socket.bind((uint16_t)IP_PORT_DHCP_SERVER); - - /* Save the current netmask to be sent in DHCP packets as the 'subnet mask option' */ - SocketAddress sock_addr; - _niface->get_ip_address(&sock_addr); - _server_addr.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address()); - _niface->get_netmask(&sock_addr); - _netmask.addrv4.addr = string_to_ipv4(sock_addr.get_ip_address()); - -#ifdef DHCP_EXTENSIVE_DEBUG - printf("DHCP Server started.\n"); - printf("DHCP Server: IP : %s\n", _niface->get_ip_address()); - printf("DHCP Server: Netmask: %s\n", _niface->get_netmask()); - printf("DHCP Server: Gateway: %s\n", _niface->get_gateway()); - printf("DHCP Server: MAC : %s\n\n", _niface->get_mac_address()); -#endif - - /* Calculate the first available IP address which will be served - based on the netmask and the local IP */ - uint32_t ip_mask = ~(_netmask.addrv4.addr); - uint32_t subnet = _server_addr.addrv4.addr & _netmask.addrv4.addr; - _available_addr.addrv4.addr = subnet | ((_server_addr.addrv4.addr + 1) & ip_mask); - - while (_running) { - /* Sleep until data is received from socket. */ - err_or_size = _socket.recv(_buff, DHCP_PACKET_SIZE); - /* Options field in DHCP header is variable length. We are looking for option "DHCP Message Type" that is 3 octets in size (code, length and type) */ - /* If the return value is <0, it is an error; if it is >=0, it is the received length */ - if (err_or_size < 0 || err_or_size < (int32_t)sizeof(dhcp_packet_t)) { - continue; - } - - dhcp_packet_t *dhcp = reinterpret_cast(_buff); - /* Check if the option in the dhcp header is "DHCP Message Type", code value for option "DHCP Message Type" is 53 as per rfc2132 */ - if (dhcp->Options[0] != DHCP_MESSAGETYPE_OPTION_CODE) { - printf("%d: %s received option code wrong: %d != %d\n", __LINE__, __func__, dhcp->Options[0], DHCP_MESSAGETYPE_OPTION_CODE); - continue; - } - - uint8_t msg_type = dhcp->Options[2]; - switch (msg_type) { - case DHCP_MSG_TYPE_DISCOVER: - handleDiscover(dhcp); - break; - case DHCP_MSG_TYPE_REQUEST: - handleRequest(dhcp); - break; - default: - printf("DHCP ERROR: Unhandled dhcp packet type, %d", msg_type); - break; - } - } -} - -void CyDhcpServer::threadWrapper(CyDhcpServer *obj) -{ - obj->runServer(); -} - -CyDhcpServer::CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface) - : _nstack(nstack), - _niface(niface), - _thread(osPriorityNormal, DHCP_STACK_SIZE, NULL, "DHCPserver") {} - -CyDhcpServer::~CyDhcpServer() -{ - stop(); -} - -cy_rslt_t CyDhcpServer::start(void) -{ - cy_rslt_t result = CY_RSLT_SUCCESS; - if (!_running) { - CY_ASSERT(_nstack != NULL); - - /* Clear cache */ - memset(_mac_addr_cache, 0, sizeof(_mac_addr_cache)); - memset(_ip_addr_cache, 0, sizeof(_ip_addr_cache)); - - /* Start DHCP server */ - if (osOK != _thread.start(mbed::callback(threadWrapper, this))) { - result = CY_DHCP_THREAD_CREATION_FAILED; - } - } - return result; -} - -cy_rslt_t CyDhcpServer::stop(void) -{ - cy_rslt_t result = CY_RSLT_SUCCESS; - if (_running) { - _running = false; - if (NSAPI_ERROR_OK != _socket.close()) { - printf("DHCP ERROR: DHCP socket closure failed.\n"); - result = CY_DHCP_STOP_FAILED; - } - if (osOK != _thread.join()) { - printf("DHCP ERROR: DHCP thread join failed.\n"); - result = CY_DHCP_STOP_FAILED; - } - } - return result; -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h deleted file mode 100644 index b11d031..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/CyDhcpServer.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WHD_DHCP_SERVER_H -#define WHD_DHCP_SERVER_H - -#include "cy_result.h" -#include "cy_syslib.h" -#include "cynetwork_utils.h" -#include "UDPSocket.h" -#include "netsocket/NetworkInterface.h" -#include "netsocket/NetworkStack.h" -#include "rtos.h" - -/* DHCP data structure */ -typedef struct { - uint8_t Opcode; /* packet opcode type */ - uint8_t HwType; /* hardware addr type */ - uint8_t HwLen; /* hardware addr length */ - uint8_t Hops; /* gateway hops */ - uint32_t TransactionId; /* transaction ID */ - uint16_t SecsElapsed; /* seconds since boot began */ - uint16_t Flags; - uint32_t ClientIpAddr; /* client IP address */ - uint32_t YourIpAddr; /* 'your' IP address */ - uint32_t ServerIpAddr; /* server IP address */ - uint32_t GatewayIpAddr; /* gateway IP address */ - uint8_t ClientHwAddr[16]; /* client hardware address */ - uint8_t Legacy[192]; /* SName, File */ - uint32_t MagicCookie; - uint8_t Options[3]; /* options area */ - /* as of RFC2131 it is variable length */ -} dhcp_packet_t; - -#define DHCP_SUBNETMASK_OPTION_CODE (1) -#define DHCP_ROUTER_OPTION_CODE (3) -#define DHCP_DNS_SERVER_OPTION_CODE (6) -#define DHCP_HOST_NAME_OPTION_CODE (12) -#define DHCP_MTU_OPTION_CODE (26) -#define DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE (50) -#define DHCP_LEASETIME_OPTION_CODE (51) -#define DHCP_MESSAGETYPE_OPTION_CODE (53) -#define DHCP_SERVER_IDENTIFIER_OPTION_CODE (54) -#define DHCP_PARAM_REQUEST_LIST_OPTION_CODE (55) -#define DHCP_WPAD_OPTION_CODE (252) -#define DHCP_END_OPTION_CODE (255) - -#define DHCP_IP_ADDRESS_CACHE_MAX (5) -#define ADDITIONAL_OPTION_BYTES (272) -#define DHCP_PACKET_SIZE (sizeof(dhcp_packet_t) + ADDITIONAL_OPTION_BYTES) - -/** DHCP thread could not be started */ -#define CY_DHCP_THREAD_CREATION_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 0) - -/** Error while trying to stop the DHCP server */ -#define CY_DHCP_STOP_FAILED CY_RSLT_CREATE(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MIDDLEWARE_BASE, 1) - -/** - * Implementation of a DHCP sever - */ -class CyDhcpServer { -public: - /** - * Create a DHCP server. - */ - CyDhcpServer(NetworkStack *nstack, NetworkInterface *niface); - - /** - * Delete the DHCP server. - */ - virtual ~CyDhcpServer(); - - /** - * Start a DHCP server instance. - * @return CY_RSLT_SUCCESS on success otherwise error. - */ - cy_rslt_t start(void); - - /** - * Stop a DHCP server instance. - * @return CY_RSLT_SUCCESS on success otherwise error. - */ - cy_rslt_t stop(void); - -private: - NetworkStack *_nstack = NULL; - NetworkInterface *_niface = NULL; - UDPSocket _socket; - Thread _thread; - bool _running = false; - - cy_ip_addr_t _available_addr; - cy_ip_addr_t _server_addr; - cy_ip_addr_t _netmask; - - cy_mac_addr_t _mac_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX]; - cy_ip_addr_t _ip_addr_cache[DHCP_IP_ADDRESS_CACHE_MAX]; - uint8_t _buff[DHCP_PACKET_SIZE]; - - static void threadWrapper(CyDhcpServer *obj); - void runServer(void); - - void setAddress(const cy_mac_addr_t &mac_id, const cy_ip_addr_t &addr); - bool lookupAddress(const cy_mac_addr_t &mac_id, cy_ip_addr_t &addr); - void freeAddress(const cy_mac_addr_t &mac_id); - - void handleDiscover(dhcp_packet_t *dhcp); - void handleRequest(dhcp_packet_t *dhcp); -}; - -#endif /* WHD_DHCP_SERVER_H */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp deleted file mode 100644 index 9c8b1d4..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* WHD Access Point Interface Implementation - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include "WhdAccessPoint.h" - -WhdAccessPoint::WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len) : - WiFiAccessPoint(ap), _bss_type(bss_type) -{ - _ie_ptr = (uint8_t *)malloc(ie_len * sizeof(uint8_t)); - if (_ie_ptr != NULL) { - _ie_len = ie_len; - memcpy(_ie_ptr, ie_ptr, ie_len * sizeof(uint8_t)); - } -} - -WhdAccessPoint &WhdAccessPoint::operator=(WhdAccessPoint &&rhs) -{ - if (this != &rhs) { - WiFiAccessPoint::operator=(rhs); - _bss_type = rhs._bss_type; - _ie_ptr = rhs._ie_ptr; - _ie_len = rhs._ie_len; - rhs._ie_ptr = NULL; - rhs._ie_len = 0; - } - return *this; -} - -whd_bss_type_t WhdAccessPoint::get_bss_type() const -{ - return _bss_type; -} - -uint8_t *WhdAccessPoint::get_ie_data() const -{ - return _ie_ptr; -} - -uint32_t WhdAccessPoint::get_ie_len() const -{ - return _ie_len; -} - -WhdAccessPoint::~WhdAccessPoint() -{ - if (_ie_ptr != NULL) { - free(_ie_ptr); - } -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h deleted file mode 100644 index 5ceaba6..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdAccessPoint.h +++ /dev/null @@ -1,74 +0,0 @@ -/* WHD Access Point Interface - * Copyright (c) 2017-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WHD_ACCESS_POINT_H -#define WHD_ACCESS_POINT_H - -#include "netsocket/WiFiAccessPoint.h" -#include "whd_types.h" - -/* Enum for scan result type */ -enum scan_result_type { - SRES_TYPE_WIFI_ACCESS_POINT, - SRES_TYPE_WHD_ACCESS_POINT -}; - -/** WhdAccessPoint class - * - * Class that represents a Whd Access Point - * which contains additional Whd specific information - */ -class WhdAccessPoint : public WiFiAccessPoint { -public: - WhdAccessPoint() : WiFiAccessPoint() {}; - WhdAccessPoint(nsapi_wifi_ap_t ap, whd_bss_type_t bss_type, uint8_t *ie_ptr, uint32_t ie_len); - - /** Define move assignment and prevent copy-assignment - * - * Due to IE element data could have large memory footprint, - * only move assignment is allowed. - */ - WhdAccessPoint &operator=(WhdAccessPoint &&rhs); - WhdAccessPoint &operator=(const WhdAccessPoint &rhs) = delete; - - /** Get WHD access point's bss type - * - * @return The whd_bss_type_t of the access point - */ - whd_bss_type_t get_bss_type() const; - - /** Get WHD access point's IE data - * - * @return The pointer to ie data buffer - */ - uint8_t *get_ie_data() const; - - /** Get WHD access point's IE length - * - * @return The ie data length - */ - uint32_t get_ie_len() const; - - virtual ~WhdAccessPoint(); - -private: - whd_bss_type_t _bss_type; - uint8_t *_ie_ptr; /**< Pointer to received Beacon/Probe Response IE(Information Element) */ - uint32_t _ie_len; /**< Length of IE(Information Element) */ -}; - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp deleted file mode 100644 index 51c3675..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/* WHD STAION implementation of NetworkInterfaceAPI - * Copyright (c) 2017-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "WhdSTAInterface.h" -#include "nsapi.h" -#include "lwipopts.h" -#include "lwip/etharp.h" -#include "lwip/ethip6.h" -#include "rtos.h" -#include "whd_emac.h" -#include "whd_wifi_api.h" -#include "whd_wlioctl.h" - -#define CMP_MAC( a, b ) (((((unsigned char*)a)[0])==(((unsigned char*)b)[0]))&& \ - ((((unsigned char*)a)[1])==(((unsigned char*)b)[1]))&& \ - ((((unsigned char*)a)[2])==(((unsigned char*)b)[2]))&& \ - ((((unsigned char*)a)[3])==(((unsigned char*)b)[3]))&& \ - ((((unsigned char*)a)[4])==(((unsigned char*)b)[4]))&& \ - ((((unsigned char*)a)[5])==(((unsigned char*)b)[5]))) - -struct whd_scan_userdata { - rtos::Semaphore *sema; - scan_result_type sres_type; - WiFiAccessPoint *aps; - std::vector *result_buff; - unsigned count; - unsigned offset; - bool scan_in_progress; -}; - -static whd_scan_userdata interal_scan_data; -static whd_scan_result_t internal_scan_result; -static uint16_t sta_link_update_entry = 0xFF; -static const whd_event_num_t sta_link_change_events[] = { - WLC_E_SET_SSID, WLC_E_LINK, WLC_E_AUTH, WLC_E_ASSOC, WLC_E_DEAUTH_IND, WLC_E_DISASSOC_IND, WLC_E_DISASSOC, - WLC_E_REASSOC, WLC_E_PSK_SUP, WLC_E_ACTION_FRAME_COMPLETE, WLC_E_NONE -}; - - -extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); - - -int whd_toerror(whd_result_t res) -{ - switch (res) { - case WHD_SUCCESS: - return NSAPI_ERROR_OK; - case WHD_UNSUPPORTED: - case WHD_WLAN_UNSUPPORTED: - case WHD_WLAN_ACM_NOTSUPPORTED: - return NSAPI_ERROR_UNSUPPORTED; - case WHD_BADARG: - case WHD_WLAN_BADARG: - return NSAPI_ERROR_PARAMETER; - case WHD_WLAN_NOTASSOCIATED: - case WHD_INVALID_JOIN_STATUS: - return NSAPI_ERROR_NO_CONNECTION; - case WHD_BUFFER_UNAVAILABLE_PERMANENT: - case WHD_BUFFER_UNAVAILABLE_TEMPORARY: - case WHD_RX_BUFFER_ALLOC_FAIL: - case WHD_BUFFER_ALLOC_FAIL: - case WHD_WLAN_NOMEM: - case WHD_MALLOC_FAILURE: - return NSAPI_ERROR_NO_MEMORY; - case WHD_ACCESS_POINT_NOT_FOUND: - case WHD_NETWORK_NOT_FOUND: - return NSAPI_ERROR_NO_SSID; - case WHD_NOT_AUTHENTICATED: - case WHD_INVALID_KEY: - case WHD_NOT_KEYED: - return NSAPI_ERROR_AUTH_FAILURE; - case WHD_PENDING: - case WHD_JOIN_IN_PROGRESS: - return NSAPI_ERROR_IN_PROGRESS; - case WHD_CONNECTION_LOST: - return NSAPI_ERROR_CONNECTION_LOST; - case WHD_TIMEOUT: - case WHD_EAPOL_KEY_PACKET_M1_TIMEOUT: - case WHD_EAPOL_KEY_PACKET_M3_TIMEOUT: - case WHD_EAPOL_KEY_PACKET_G1_TIMEOUT: - return NSAPI_ERROR_CONNECTION_TIMEOUT; - case WHD_WLAN_BUSY: - return NSAPI_ERROR_BUSY; - case WHD_WLAN_NODEVICE: - return NSAPI_ERROR_DEVICE_ERROR; - default: - return -res; - } -} - -static nsapi_security_t whd_tosecurity(whd_security_t sec) -{ - switch (sec) { - case WHD_SECURITY_OPEN: - return NSAPI_SECURITY_NONE; - case WHD_SECURITY_WEP_PSK: - case WHD_SECURITY_WEP_SHARED: - return NSAPI_SECURITY_WEP; - case WHD_SECURITY_WPA_MIXED_PSK: - case WHD_SECURITY_WPA_TKIP_PSK: - case WHD_SECURITY_WPA_TKIP_ENT: - return NSAPI_SECURITY_WPA; - case WHD_SECURITY_WPA2_WPA_AES_PSK: - case WHD_SECURITY_WPA2_WPA_MIXED_PSK: - return NSAPI_SECURITY_WPA_WPA2; - case WHD_SECURITY_WPA2_MIXED_ENT: - return NSAPI_SECURITY_WPA2_ENT; - case WHD_SECURITY_WPA2_MIXED_PSK: - case WHD_SECURITY_WPA2_AES_PSK: - case WHD_SECURITY_WPA2_AES_ENT: - case WHD_SECURITY_WPA2_FBT_PSK: - case WHD_SECURITY_WPA2_FBT_ENT: - return NSAPI_SECURITY_WPA2; - case WHD_SECURITY_WPA3_SAE: - return NSAPI_SECURITY_WPA3; - case WHD_SECURITY_WPA3_WPA2_PSK: - return NSAPI_SECURITY_WPA3_WPA2; - default: - return NSAPI_SECURITY_UNKNOWN; - } -} - -whd_security_t whd_fromsecurity(nsapi_security_t sec) -{ - switch (sec) { - case NSAPI_SECURITY_NONE: - return WHD_SECURITY_OPEN; - case NSAPI_SECURITY_WEP: - return WHD_SECURITY_WEP_PSK; - case NSAPI_SECURITY_WPA: - return WHD_SECURITY_WPA_MIXED_PSK; - case NSAPI_SECURITY_WPA2: - return WHD_SECURITY_WPA2_AES_PSK; - case NSAPI_SECURITY_WPA_WPA2: - return WHD_SECURITY_WPA2_MIXED_PSK; - case NSAPI_SECURITY_WPA2_ENT: - return WHD_SECURITY_WPA2_MIXED_ENT; - case NSAPI_SECURITY_WPA3: - return WHD_SECURITY_WPA3_SAE; - case NSAPI_SECURITY_WPA3_WPA2: - return WHD_SECURITY_WPA3_WPA2_PSK; - default: - return WHD_SECURITY_UNKNOWN; - } -} - -static void *whd_wifi_link_state_change_handler(whd_interface_t ifp, - const whd_event_header_t *event_header, - const uint8_t *event_data, - void *handler_user_data) -{ - UNUSED_PARAMETER(event_data); - - if (event_header->bsscfgidx >= WHD_INTERFACE_MAX) { - WPRINT_WHD_DEBUG(("%s: event_header: Bad interface\n", __FUNCTION__)); - return NULL; - } - - if ((event_header->event_type == WLC_E_DEAUTH_IND) || - (event_header->event_type == WLC_E_DISASSOC_IND) || - ((event_header->event_type == WLC_E_PSK_SUP) && - (event_header->status == WLC_SUP_KEYED) && - (event_header->reason == WLC_E_SUP_DEAUTH))) { - whd_emac_wifi_link_state_changed(ifp, WHD_FALSE); - return handler_user_data; - } - - if (((event_header->event_type == WLC_E_PSK_SUP) && - (event_header->status == WLC_SUP_KEYED) && - (event_header->reason == WLC_E_SUP_OTHER)) || - (whd_wifi_is_ready_to_transceive(ifp) == WHD_SUCCESS)) { - whd_emac_wifi_link_state_changed(ifp, WHD_TRUE); - return handler_user_data; - } - - return handler_user_data; -} - - -MBED_WEAK WhdSTAInterface::OlmInterface &WhdSTAInterface::OlmInterface::get_default_instance() -{ - static OlmInterface olm; - return olm; -} - -WhdSTAInterface::WhdSTAInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, OlmInterface &olm, whd_interface_shared_info_t &shared) - : EMACInterface(emac, stack), - _ssid("\0"), - _pass("\0"), - _security(NSAPI_SECURITY_NONE), - _whd_emac(emac), - _olm(&olm), - _iface_shared(shared) -{ -} - -nsapi_error_t WhdSTAInterface::connect( - const char *ssid, const char *pass, - nsapi_security_t security, - uint8_t channel) -{ - int err = set_channel(channel); - if (err) { - return err; - } - - err = set_credentials(ssid, pass, security); - if (err) { - return err; - } - - return connect(); -} - -nsapi_error_t WhdSTAInterface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) -{ - if ((ssid == NULL) || - (strlen(ssid) == 0) || - (pass == NULL && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) || - (strlen(pass) == 0 && (security != NSAPI_SECURITY_NONE && security != NSAPI_SECURITY_WPA2_ENT)) || - (strlen(pass) > 63 && (security == NSAPI_SECURITY_WPA2 || security == NSAPI_SECURITY_WPA || - security == NSAPI_SECURITY_WPA_WPA2 || security == NSAPI_SECURITY_WPA3 || security == NSAPI_SECURITY_WPA3_WPA2)) - ) { - return NSAPI_ERROR_PARAMETER; - } - - memset(_ssid, 0, sizeof(_ssid)); - strncpy(_ssid, ssid, sizeof(_ssid)); - - memset(_pass, 0, sizeof(_pass)); - strncpy(_pass, pass, sizeof(_pass)); - - _security = security; - - return NSAPI_ERROR_OK; -} - -nsapi_error_t WhdSTAInterface::connect() -{ - ScopedMutexLock lock(_iface_shared.mutex); - -#define MAX_RETRY_COUNT ( 5 ) - int i; - whd_result_t res; - - // initialize wiced, this is noop if already init - if (!_whd_emac.powered_up) { - if(!_whd_emac.power_up()) { - return NSAPI_ERROR_DEVICE_ERROR; - } - } - - res = whd_management_set_event_handler(_whd_emac.ifp, sta_link_change_events, - whd_wifi_link_state_change_handler, NULL, &sta_link_update_entry); - if (res != WHD_SUCCESS) { - return whd_toerror(res); - } - - _iface_shared.if_status_flags |= IF_STATUS_STA_UP; - _iface_shared.default_if_cfg = DEFAULT_IF_STA; - if (!_interface) { - nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); - if (err != NSAPI_ERROR_OK) { - _interface = NULL; - return err; - } - _interface->attach(_connection_status_cb); - _iface_shared.iface_sta = _interface; - } else { - _stack.set_default_interface(_interface); - } - - // Initialize the Offload Manager - if (_olm != NULL) { - _olm->init_ols(_whd_emac.ifp, this); - } - - if ((_ssid == NULL) || - (strlen(_ssid) == 0)) { - return NSAPI_ERROR_PARAMETER; - } - - // setup ssid - whd_ssid_t ssid; - strncpy((char *)ssid.value, _ssid, SSID_NAME_SIZE); - ssid.value[SSID_NAME_SIZE - 1] = '\0'; - ssid.length = strlen((char *)ssid.value); - - // choose network security - whd_security_t security = whd_fromsecurity(_security); - -#if defined MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK - /* Set PSK password for WPA3_WPA2 */ - if (security == WHD_SECURITY_WPA3_WPA2_PSK) { - res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK, - strlen(MBED_CONF_APP_WIFI_PASSWORD_WPA2PSK), WHD_SECURITY_WPA3_WPA2_PSK ); - } -#else - /* Set PSK password for WPA3_WPA2 */ - if (security == WHD_SECURITY_WPA3_WPA2_PSK) { - res = (whd_result_t)whd_wifi_enable_sup_set_passphrase( _whd_emac.ifp, (const uint8_t *)_pass, - strlen(_pass), WHD_SECURITY_WPA3_WPA2_PSK ); - } -#endif - // join the network - for (i = 0; i < MAX_RETRY_COUNT; i++) { - res = (whd_result_t)whd_wifi_join(_whd_emac.ifp, - &ssid, - security, - (const uint8_t *)_pass, strlen(_pass)); - if (res == WHD_SUCCESS) { - break; - } - } - - if (res != WHD_SUCCESS) { - return whd_toerror(res); - } - - if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) { - whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE); - } - - // bring up - return _interface->bringup(_dhcp, - _ip_address[0] ? _ip_address : 0, - _netmask[0] ? _netmask : 0, - _gateway[0] ? _gateway : 0, - DEFAULT_STACK); -} - -void WhdSTAInterface::wifi_on() -{ - if (!_whd_emac.powered_up) { - if(!_whd_emac.power_up()) { - CY_ASSERT(false); - } - } -} - -nsapi_error_t WhdSTAInterface::disconnect() -{ - ScopedMutexLock lock(_iface_shared.mutex); - - if (!_interface) { - return NSAPI_STATUS_DISCONNECTED; - } - - // bring down - int err = _interface->bringdown(); - if (err) { - return err; - } - - _iface_shared.if_status_flags &= ~IF_STATUS_STA_UP; - if (_iface_shared.if_status_flags & IF_STATUS_SOFT_AP_UP) { - _iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP; - _stack.set_default_interface(_iface_shared.iface_softap); - } else { - _iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET; - } - - // leave network - whd_result_t res = whd_wifi_leave(_whd_emac.ifp); - if (res != WHD_SUCCESS) { - return whd_toerror(res); - } - whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_FALSE); - - // remove the interface added in connect - if (_interface) { - nsapi_error_t err = _stack.remove_ethernet_interface(&_interface); - if (err != NSAPI_ERROR_OK) { - return err; - } - _iface_shared.iface_sta = NULL; - } - - res = whd_wifi_deregister_event_handler(_whd_emac.ifp, sta_link_update_entry); - if (res != WHD_SUCCESS) { - return whd_toerror(res); - } - - // de-init Offload Manager - if (_olm != NULL) { - _olm->deinit_ols(); - } - - return NSAPI_ERROR_OK; -} - -int8_t WhdSTAInterface::get_rssi() -{ - int32_t rssi; - whd_result_t res; - - if (!_whd_emac.powered_up) { - if(!_whd_emac.power_up()) { - CY_ASSERT(false); - } - } - - res = (whd_result_t)whd_wifi_get_rssi(_whd_emac.ifp, &rssi); - if (res != 0) { - /* The network GT tests expect that this function should return 0 in case of an error and not assert */ - return 0; - } - - return (int8_t)rssi; -} - -static void whd_scan_handler(whd_scan_result_t **result_ptr, - void *user_data, whd_scan_status_t status) -{ - - whd_scan_userdata *data = (whd_scan_userdata *)user_data; - - /* Even after stopping scan, some results will still come as results are already present in the queue */ - if (data->scan_in_progress == false) { - return; - } - - // finished scan, either succesfully or through an abort - if (status != WHD_SCAN_INCOMPLETE) { - data->scan_in_progress = false; - data->sema->release(); - return; - } - - // can't really keep anymore scan results - if (data->count > 0 && data->offset >= data->count) { - /* We can not abort the scan as this function is getting executed in WHD context, - Note that to call any WHD API, caller function should not in WHD context */ - return; - } - - whd_scan_result_t *record = *result_ptr; - - for (unsigned int i = 0; i < data->result_buff->size(); i++) { - if (CMP_MAC((*data->result_buff)[i].BSSID.octet, record->BSSID.octet)) { - return; - } - } - - if (data->count > 0 && data->aps != NULL) { - // get ap stats - nsapi_wifi_ap ap; - uint8_t length = record->SSID.length; - if (length < sizeof(ap.ssid) - 1) { - length = sizeof(ap.ssid) - 1; - } - memcpy(ap.ssid, record->SSID.value, length); - ap.ssid[length] = '\0'; - - memcpy(ap.bssid, record->BSSID.octet, sizeof(ap.bssid)); - - ap.security = whd_tosecurity(record->security); - ap.rssi = record->signal_strength; - ap.channel = record->channel; - if (data->sres_type == SRES_TYPE_WIFI_ACCESS_POINT) { - data->aps[data->offset] = WiFiAccessPoint(ap); - } else if (data->sres_type == SRES_TYPE_WHD_ACCESS_POINT) { - WhdAccessPoint *aps_sres = static_cast(data->aps); - aps_sres[data->offset] = std::move(WhdAccessPoint(ap, record->bss_type, - record->ie_ptr, record->ie_len)); - } - } - - // store to result_buff for future duplication removal - data->result_buff->push_back(*record); - data->offset = data->result_buff->size(); -} - -int WhdSTAInterface::internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type) -{ - ScopedMutexLock lock(_iface_shared.mutex); - - // initialize wiced, this is noop if already init - if (!_whd_emac.powered_up) { - if(!_whd_emac.power_up()) { - return NSAPI_ERROR_DEVICE_ERROR; - } - } - - interal_scan_data.sema = new Semaphore(); - interal_scan_data.sres_type = sres_type; - interal_scan_data.aps = aps; - interal_scan_data.count = count; - interal_scan_data.offset = 0; - interal_scan_data.scan_in_progress = true; - interal_scan_data.result_buff = new std::vector(); - whd_result_t whd_res; - int res; - - whd_res = (whd_result_t)whd_wifi_scan(_whd_emac.ifp, WHD_SCAN_TYPE_ACTIVE, WHD_BSS_TYPE_ANY, - NULL, NULL, NULL, NULL, whd_scan_handler, &internal_scan_result, &interal_scan_data); - if (whd_res != WHD_SUCCESS) { - res = whd_toerror(whd_res); - } else { - interal_scan_data.sema->acquire(); - res = interal_scan_data.offset; - } - - delete interal_scan_data.sema; - delete interal_scan_data.result_buff; - return res; -} - -int WhdSTAInterface::scan(WiFiAccessPoint *aps, unsigned count) -{ - return internal_scan(aps, count, SRES_TYPE_WIFI_ACCESS_POINT); -} - -int WhdSTAInterface::scan_whd(WhdAccessPoint *aps, unsigned count) -{ - return internal_scan(aps, count, SRES_TYPE_WHD_ACCESS_POINT); -} - -int WhdSTAInterface::is_interface_connected(void) -{ - if (!_whd_emac.ifp) { - return WHD_INTERFACE_NOT_UP; - } - _whd_emac.ifp->role = WHD_STA_ROLE; - if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) { - return WHD_SUCCESS; - } else { - return WHD_CONNECTION_LOST; - } -} - -int WhdSTAInterface::get_bssid(uint8_t *bssid) -{ - whd_mac_t ap_mac; - whd_result_t res = WHD_SUCCESS; - - memset(&ap_mac, 0, sizeof(ap_mac)); - _whd_emac.ifp->role = WHD_STA_ROLE; - if ((whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS)) { - res = whd_wifi_get_bssid(_whd_emac.ifp, &ap_mac); - - if (res == WHD_SUCCESS) { - memcpy(bssid, ap_mac.octet, sizeof(ap_mac.octet)); - } - } - return res; -} - -int WhdSTAInterface::whd_log_print(void) -{ - return whd_wifi_print_whd_log(_whd_emac.drvp); -} - -int WhdSTAInterface::whd_log_read(char *buffer, int buffer_size) -{ - whd_result_t res = WHD_SUCCESS; - if (buffer != NULL) { - res = whd_wifi_read_wlan_log(_whd_emac.drvp, buffer, buffer_size); - } - return res; -} - -nsapi_error_t WhdSTAInterface::wifi_get_ac_params_sta(void *acp) -{ - whd_result_t res = WHD_SUCCESS; - edcf_acparam_t *ac_param = (edcf_acparam_t *)acp; - - res = whd_wifi_get_acparams(_whd_emac.ifp, ac_param); - if (res != WHD_SUCCESS) { - return res; - } - return res; -} - -int WhdSTAInterface::wifi_set_iovar_value(const char *iovar, uint32_t value) -{ - whd_result_t res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_set_iovar_value(_whd_emac.ifp, iovar, value); - return res; -} - -int WhdSTAInterface::wifi_get_iovar_value(const char *iovar, uint32_t *value) -{ - int res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_get_iovar_value(_whd_emac.ifp, iovar, value); - return res; -} -int WhdSTAInterface::wifi_set_ioctl_value(uint32_t ioctl, uint32_t value) -{ - int res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_set_ioctl_value(_whd_emac.ifp, ioctl, value); - return res; -} - -int WhdSTAInterface::wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value ) -{ - int res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_get_ioctl_value(_whd_emac.ifp, ioctl, value); - return res; -} - -int WhdSTAInterface::wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len) -{ - int res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_get_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len); - return res; -} - -int WhdSTAInterface::wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len) -{ - int res = WHD_SUCCESS; - _whd_emac.ifp->role = WHD_STA_ROLE; - res = whd_wifi_set_ioctl_buffer(_whd_emac.ifp, ioctl, buffer, len); - return res; -} - -int WhdSTAInterface::wifi_get_ifp(whd_interface_t *ifp) -{ - int res = WHD_SUCCESS; - *ifp = _whd_emac.ifp; - return res; -} - -int WhdSTAInterface::wifi_set_up(void) -{ - int res = WHD_SUCCESS; - res = whd_wifi_set_up(_whd_emac.ifp); - return res; -} - -int WhdSTAInterface::wifi_set_down(void) -{ - int res = WHD_SUCCESS; - res = whd_wifi_set_down(_whd_emac.ifp); - return res; -} - -int WhdSTAInterface::wifi_set_coex_config(whd_coex_config_t *coex_config) -{ - int res = WHD_SUCCESS; - res = whd_wifi_set_coex_config(_whd_emac.ifp, coex_config); - return res; -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h deleted file mode 100644 index 4dd1098..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSTAInterface.h +++ /dev/null @@ -1,263 +0,0 @@ -/* WHD implementation of NetworkInterfaceAPI - * Copyright (c) 2017-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WHD_STA_INTERFACE_H -#define WHD_STA_INTERFACE_H - -#include "netsocket/WiFiInterface.h" -#include "netsocket/EMACInterface.h" -#include "netsocket/OnboardNetworkStack.h" -#include "WhdAccessPoint.h" -#include "whd_emac.h" -#include "whd_interface.h" -#include "whd_types_int.h" - -struct ol_desc; - -/** WhdSTAInterface class - * Implementation of the NetworkStack for the WHD - */ -class WhdSTAInterface : public WiFiInterface, public EMACInterface { -public: - class OlmInterface { - public: - /** Get the default OLM interface. */ - static OlmInterface &get_default_instance(); - - OlmInterface(struct ol_desc *list = NULL) {} - - virtual int init_ols(void *whd, void *ip) - { - return 0; - } - virtual int sleep() - { - return 0; - } - virtual int wake() - { - return 0; - } - - virtual void deinit_ols(void) {} - }; - - WhdSTAInterface( - WHD_EMAC &emac = WHD_EMAC::get_instance(), - OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(), - OlmInterface &olm = OlmInterface::get_default_instance(), - whd_interface_shared_info_t &shared = whd_iface_shared); - - static WhdSTAInterface *get_default_instance(); - - /* Turn on the wifi device*/ - void wifi_on(); - - /** Start the interface - * - * Attempts to connect to a WiFi network. Requires ssid and passphrase to be set. - * If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned. - * - * @return 0 on success, negative error code on failure - */ - nsapi_error_t connect(); - - /** Start the interface - * - * Attempts to connect to a WiFi network. - * - * @param ssid Name of the network to connect to - * @param pass Security passphrase to connect to the network - * @param security Type of encryption for connection (Default: NSAPI_SECURITY_NONE) - * @param channel This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED - * @return 0 on success, or error code on failure - */ - nsapi_error_t connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE, uint8_t channel = 0); - - /** Stop the interface - * @return 0 on success, negative on failure - */ - nsapi_error_t disconnect(); - - /** Set the WiFi network credentials - * - * @param ssid Name of the network to connect to - * @param pass Security passphrase to connect to the network - * @param security Type of encryption for connection - * (defaults to NSAPI_SECURITY_NONE) - * @return 0 on success, or error code on failure - */ - nsapi_error_t set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE); - - /** Set the WiFi network channel - NOT SUPPORTED - * - * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED - * - * @param channel Channel on which the connection is to be made, or 0 for any (Default: 0) - * @return Not supported, returns NSAPI_ERROR_UNSUPPORTED - */ - nsapi_error_t set_channel(uint8_t channel) - { - if (channel != 0) { - return NSAPI_ERROR_UNSUPPORTED; - } - - return 0; - } - - /** Set blocking status of interface. - * Nonblocking mode unsupported. - * - * @param blocking true if connect is blocking - * @return 0 on success, negative error code on failure - */ - nsapi_error_t set_blocking(bool blocking) - { - if (blocking) { - _blocking = blocking; - return NSAPI_ERROR_OK; - } else { - return NSAPI_ERROR_UNSUPPORTED; - } - } - - /** Gets the current radio signal strength for active connection - * - * @return Connection strength in dBm (negative value) - */ - int8_t get_rssi(); - - /** Scan for available networks in WiFiAccessPoint format - * - * This function will block. - * - * @param ap Pointer to allocated array of WiFiAccessPoint format for discovered AP - * @param count Size of allocated @a res array, or 0 to only count available AP - * @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0) - * @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error - * see @a nsapi_error - */ - int scan(WiFiAccessPoint *res, unsigned count); - - /** Scan for available networks in WhdAccessPoint format - * - * This function will block. - * - * @param ap Pointer to allocated array of WhdAccessPoint format for discovered AP - * @param count Size of allocated @a res array, or 0 to only count available AP - * @param timeout Timeout in milliseconds; 0 for no timeout (Default: 0) - * @return Number of entries in @a, or if @a count was 0 number of available networks, negative on error - * see @a nsapi_error - */ - int scan_whd(WhdAccessPoint *res, unsigned count); - - /* is interface connected, if yes return WICED_SUCCESS else WICED_NOT_CONNECTED */ - int is_interface_connected(); - - /* get bssid of the AP if success return WICED_SUCCESS else WICED_ERROR */ - int get_bssid(uint8_t *bssid); - - /* print WHD log (this routine will malloc/free a buffer - * You need to enable printing with WHD_LOGGING_BUFFER_ENABLE - */ - int whd_log_print(void); - - /* read WHD log */ - int whd_log_read(char *buffer, int buffer_size); - - /* Get EDCF AC params */ - nsapi_error_t wifi_get_ac_params_sta(void *ac_param); - - /* get iovar value */ - int wifi_get_iovar_value(const char *iovar, uint32_t *value); - - /* set iovar value */ - int wifi_set_iovar_value(const char *iovar, uint32_t value); - - /* set ioctl value */ - int wifi_set_ioctl_value(uint32_t ioctl, uint32_t value) ; - - /* get ioctl value */ - int wifi_get_ioctl_value(uint32_t ioctl, uint32_t *value); - - /* get ioctl buffer */ - int wifi_get_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len); - - /* set ioctl buffer */ - int wifi_set_ioctl_buffer(uint32_t ioctl, uint8_t *buffer, uint16_t len); - - /* get WHD ifp value */ - int wifi_get_ifp(whd_interface_t *ifp); - - /* set wifi interface up */ - int wifi_set_up(void); - - /* set wifi interface down */ - int wifi_set_down(void); - - /* set wifi coex configuration */ - int wifi_set_coex_config(whd_coex_config_t *coex_config); - - /** Set Offload Manager Information - * NOTE: Only allowed while disconnected - * - * @param olm Offload Manager info structure - * @return true if completed successfully - * false if Interface is connected - */ - int set_olm(OlmInterface *olm) - { - if (get_connection_status() == NSAPI_STATUS_DISCONNECTED) { - _olm = olm; - return true; - } - return false; - } - - /** Network stack is suspended - * - * @return 0 if successful - */ - int net_suspended() - { - int ret = _olm->sleep(); - return ret; - } - - /** Network stack is resuming - * - * @return 0 if successful - */ - int net_resuming() - { - int ret = _olm->wake(); - return ret; - } - -protected: - int internal_scan(WiFiAccessPoint *aps, unsigned count, scan_result_type sres_type); - -private: - char _ssid[33]; /* The longest possible name (defined in 802.11) +1 for the \0 */ - char _pass[64]; /* The longest allowed passphrase + 1 */ - nsapi_security_t _security; - WHD_EMAC &_whd_emac; - OlmInterface *_olm; - whd_interface_shared_info_t &_iface_shared; -}; - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp deleted file mode 100644 index e3c499c..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "nsapi.h" -#include "lwipopts.h" -#include "WhdSoftAPInterface.h" -#include "nsapi.h" -#include "lwipopts.h" -#include "lwip/etharp.h" -#include "lwip/ethip6.h" -#include "rtos.h" -#include "whd_emac.h" -#include "whd_wifi_api.h" - - -extern int whd_toerror(whd_result_t res); -extern nsapi_security_t whd_tosecurity(whd_security_t sec); -extern whd_security_t whd_fromsecurity(nsapi_security_t sec); -extern "C" void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); - -static const whd_event_num_t ap_events[] = { WLC_E_LINK, WLC_E_IF, WLC_E_DEAUTH, WLC_E_DEAUTH_IND, WLC_E_DISASSOC, WLC_E_DISASSOC_IND, WLC_E_ASSOC_IND, WLC_E_REASSOC_IND, WLC_E_NONE }; - -static void *whd_default_handle_softap_events(whd_interface_t ifp, const whd_event_header_t *event_header, - const uint8_t *event_data, void *handler_user_data) -{ - whd_driver_t whd_driver = ifp->whd_driver; - - UNUSED_PARAMETER(event_header); - UNUSED_PARAMETER(event_data); - UNUSED_PARAMETER(handler_user_data); - - WHD_IOCTL_LOG_ADD_EVENT(whd_driver, event_header->event_type, event_header->flags, event_header->reason); - - if ((event_header->event_type == (whd_event_num_t)WLC_E_LINK) || - (event_header->event_type == WLC_E_IF)) { - if (osSemaphoreGetCount(whd_driver->ap_info.whd_wifi_sleep_flag) < 1) { - osStatus_t result = osSemaphoreRelease(whd_driver->ap_info.whd_wifi_sleep_flag); - if (result != osOK) { - printf("Release whd_wifi_sleep_flag ERROR: %d", result); - } - } - } - return handler_user_data; -} - - -WhdSoftAPInterface::WhdSoftAPInterface(WHD_EMAC &emac, OnboardNetworkStack &stack, whd_interface_shared_info_t &shared) - : EMACInterface(emac, stack), - _whd_emac(emac), - _iface_shared(shared) -{ - -} - - -int WhdSoftAPInterface::start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel, - bool start_dhcp_server, const whd_custom_ie_info_t *ie_info, bool ap_sta_concur) -{ - ScopedMutexLock lock(_iface_shared.mutex); - - nsapi_error_t err; - // power up primary emac interface first - if (ap_sta_concur) { - WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE); - if (!emac_prime.power_up()) { - printf("Primary interface power up ERROR!\n"); - return NSAPI_ERROR_DEVICE_ERROR; - } - } - - // set concurrency mode and power up secondary, the bsp init is done by primary emac - _whd_emac.ap_sta_concur = ap_sta_concur; - if (!_whd_emac.power_up()) { - printf("Secondary interface power up ERROR!\n"); - return NSAPI_ERROR_DEVICE_ERROR; - } - - // setup ssid - whd_ssid_t whd_ssid; - strncpy((char *)whd_ssid.value, ssid, SSID_NAME_SIZE); - whd_ssid.value[SSID_NAME_SIZE - 1] = '\0'; - whd_ssid.length = strlen((char *)whd_ssid.value); - - // choose network security - whd_security_t whd_security = whd_fromsecurity(security); - - /* set up the AP info */ - err = whd_wifi_init_ap(_whd_emac.ifp, &whd_ssid, whd_security, (const uint8_t *)pass, - strlen(pass), channel); - if (err != NSAPI_ERROR_OK) { - printf("whd_wifi_init_ap() ERROR: %d\n", err); - return err; - } - - // update default softap interface event handler - err = unregister_event_handler(); - if (err != NSAPI_ERROR_OK) { - printf("unregister_event_handler() ERROR: %d\n", err); - return err; - } - err = register_event_handler(whd_default_handle_softap_events); - if (err != NSAPI_ERROR_OK) { - printf("register_event_handler() ERROR: %d\n", err); - return err; - } - - _iface_shared.if_status_flags |= IF_STATUS_SOFT_AP_UP; - if (!ap_sta_concur || (_iface_shared.default_if_cfg == DEFAULT_IF_NOT_SET)) { - _iface_shared.default_if_cfg = DEFAULT_IF_SOFT_AP; - } - if (!_interface) { - nsapi_error_t err = _stack.add_ethernet_interface(_whd_emac, _iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP, &_interface); - if (err != NSAPI_ERROR_OK) { - _interface = NULL; - return err; - } - _interface->attach(_connection_status_cb); - _iface_shared.iface_softap = _interface; - } else if (_iface_shared.default_if_cfg == DEFAULT_IF_SOFT_AP) { - _stack.set_default_interface(_interface); - } - - if (ie_info) { - err = whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_ADD_CUSTOM_IE, (const uint8_t *)ie_info->oui, - ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets); - if (err != NSAPI_ERROR_OK) { - printf("whd_wifi_manage_custom_ie() ERROR: %d\n", err); - return err; - } - } - - err = whd_wifi_start_ap(_whd_emac.ifp); - if (err != NSAPI_ERROR_OK) { - printf("whd_wifi_start_ap() ERROR: %d\n", err); - return err; - } - - // Set static IP address for SoftAP and bring up - set_dhcp(false); - - if (whd_wifi_is_ready_to_transceive(_whd_emac.ifp) == WHD_SUCCESS) { - whd_emac_wifi_link_state_changed(_whd_emac.ifp, WHD_TRUE); - } - - err = _interface->bringup(_dhcp, - _ip_address[0] ? _ip_address : 0, - _netmask[0] ? _netmask : 0, - _gateway[0] ? _gateway : 0, - DEFAULT_STACK); - if (err != NSAPI_ERROR_OK) { - printf("bringup() ERROR: %d\n", err); - } - - if (start_dhcp_server) { - _dhcp_server = std::make_unique(get_stack(), this); - if (CY_RSLT_SUCCESS != _dhcp_server->start()) { - err = NSAPI_ERROR_DHCP_FAILURE; - } - } - return err; -} - - - -int WhdSoftAPInterface::stop(void) -{ - ScopedMutexLock lock(_iface_shared.mutex); - - if (_dhcp_server && CY_RSLT_SUCCESS != _dhcp_server->stop()) { - return NSAPI_ERROR_DHCP_FAILURE; - } - _dhcp_server.reset(); - - // bring down - int err = _interface->bringdown(); - if (err) { - return err; - } - - _iface_shared.if_status_flags &= ~IF_STATUS_SOFT_AP_UP; - if ((_iface_shared.if_status_flags & IF_STATUS_STA_UP) == 0) { - _iface_shared.default_if_cfg = DEFAULT_IF_NOT_SET; - } - - // stop softap - whd_result_t res = whd_wifi_stop_ap(_whd_emac.ifp); - if (res != WHD_SUCCESS) { - return whd_toerror(res); - } - - // remove the interface added in start - if (_interface) { - nsapi_error_t err = _stack.remove_ethernet_interface(&_interface); - if (err != NSAPI_ERROR_OK) { - return err; - } - _iface_shared.iface_softap = NULL; - } - return NSAPI_ERROR_OK; -} - -int WhdSoftAPInterface::remove_custom_ie(const whd_custom_ie_info_t *ie_info) -{ - return whd_wifi_manage_custom_ie(_whd_emac.ifp, WHD_REMOVE_CUSTOM_IE, (const uint8_t *)ie_info->oui, - ie_info->subtype, (const void *)ie_info->data, ie_info->length, ie_info->which_packets); -} - -int WhdSoftAPInterface::get_associated_client_list(void *client_list_buffer, uint16_t buffer_length) -{ - - return whd_wifi_get_associated_client_list(_whd_emac.ifp, client_list_buffer, buffer_length); -} - -int WhdSoftAPInterface::register_event_handler(whd_event_handler_t softap_event_handler) -{ - uint16_t ap_events_entry = _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY]; - return whd_management_set_event_handler(_whd_emac.ifp, ap_events, softap_event_handler, NULL, &ap_events_entry); -} - -int WhdSoftAPInterface::unregister_event_handler(void) -{ - return whd_wifi_deregister_event_handler(_whd_emac.ifp, _whd_emac.ifp->event_reg_list[WHD_AP_EVENT_ENTRY]); -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h deleted file mode 100644 index ced7c04..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/WhdSoftAPInterface.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef WHD_SOFTAP_INTERFACE_H -#define WHD_SOFTAP_INTERFACE_H - -#include "netsocket/EMACInterface.h" -#include "netsocket/OnboardNetworkStack.h" -#include "whd_emac.h" -#include "CyDhcpServer.h" -#include "whd_interface.h" -#include - -/** - * Vendor IE details - */ -typedef struct { - uint8_t oui[WIFI_IE_OUI_LENGTH]; /**< Unique identifier for the IE */ - uint8_t subtype; /**< Sub-type of the IE */ - void *data; /**< Pointer to IE data */ - uint16_t length; /**< IE data length */ - uint16_t which_packets; /**< Mask of the packet in which this IE details to be included */ -} whd_custom_ie_info_t; - - - -/** WhdSoftAPInterface class - * Implementation of the SoftAPInterface for the Whd - */ -class WhdSoftAPInterface : public EMACInterface { -public: - /** Construct SoftAP interface - * @return pointer to default WhdSoftAPInterface instance - */ - WhdSoftAPInterface(WHD_EMAC &emac = WHD_EMAC::get_instance(WHD_AP_ROLE), - OnboardNetworkStack &stack = OnboardNetworkStack::get_default_instance(), - whd_interface_shared_info_t &shared = whd_iface_shared); - - /** Get the default WhdSoftAPInterface instance. - * @return pointer to default WhdSoftAPInterface instance - */ - static WhdSoftAPInterface *get_default_instance(); - - /** Set static IP address for SoftAP - * - * Configures the static IP address of SoftAP - * Requires that the network is stopped. - * - * @param ip_address Null-terminated representation of the local IP address - * @param netmask Null-terminated representation of the local network mask - * @param gateway Null-terminated representation of the local gateway - * @return 0 on success, negative error code on failure - * int set_network(const char *ip_address, const char *netmask, const char *gateway); - */ - - /** Start a SoftAP - * - * @param ssid Name of the SoftAP to create - * @param pass Security passphrase for connection to SoftAP - * @param security Type of encryption for connection - * @param channel Channel for SoftAP - * @param start_dhcp_server Start dhcp server for connection - * @param whd_custom_ie Optional Custom IE - * @param ap_sta_concur Enable STA+AP concurrency mode - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int start(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel, - bool start_dhcp_server = true, const whd_custom_ie_info_t *ie_info = NULL, bool ap_sta_concur = false); - - /** - * Remove Wi-Fi custom IE - * - * @param[in] ie_info : Pointer to the structure which contains custom IE information - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int remove_custom_ie(const whd_custom_ie_info_t *ie_info); - - /** Stop the Software Access Point - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int stop(void); - - /** - * Gets information about associated clients. - * - * @note Only applicable if softAP interface is up - * - * @param[out] client_list_buffer : pointer to a buffer that will be populated with a variable length structure defined by @ref whd_maclist_t - * @param[in] buffer_length : length of the buffer - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int get_associated_client_list(void *client_list_buffer, uint16_t buffer_length); - - - /** - * Register soft AP event handler - * - * @param[in] softap_event_handler : A function pointer to the event handler - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int register_event_handler(whd_event_handler_t softap_event_handler); - - /** - * Unregister soft AP event handler - * - * @return 0 on success, or error code on failure - * see @a nsapi_error - */ - int unregister_event_handler(void); - - /** Set blocking status of interface. - * Nonblocking mode unsupported. - * - * @param blocking true if connect is blocking - * @return 0 on success, negative error code on failure - */ - nsapi_error_t set_blocking(bool blocking) - { - if (blocking) { - _blocking = blocking; - return NSAPI_ERROR_OK; - } else { - return NSAPI_ERROR_UNSUPPORTED; - } - } - -protected: - WHD_EMAC &_whd_emac; - std::unique_ptr _dhcp_server; - whd_interface_shared_info_t &_iface_shared; -}; - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h deleted file mode 100644 index 5234065..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/emac_eapol.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2019 Cypress Semiconductor Corporation - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef INCLUDED_EMAC_EAPOL_H_ -#define INCLUDED_EMAC_EAPOL_H_ - -#include "whd.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/****************************************************** - * Macros - ******************************************************/ - -/****************************************************** - * Constants - ******************************************************/ -#define EAPOL_PACKET_TYPE (0x888E) - -/****************************************************** - * Enumerations - ******************************************************/ - -/****************************************************** - * Type Definitions - ******************************************************/ - -typedef whd_buffer_t whd_eapol_packet_t; - -typedef void (*eapol_packet_handler_t)(whd_interface_t interface, whd_buffer_t buffer); - -/****************************************************** - * Structures - ******************************************************/ - -/****************************************************** - * Global Variables - ******************************************************/ - -/****************************************************** - * Function Declarations - ******************************************************/ -whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler); -void emac_unregister_eapol_packet_handler(void); - -#ifdef __cplusplus -} /* extern "C" */ -#endif -#endif /* ifndef INCLUDED_EMAC_EAPOL_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp deleted file mode 100644 index 138bd8b..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" -#include "whd_emac.h" -#include "lwip/etharp.h" -#include "lwip/ethip6.h" -#include "mbed_shared_queues.h" -#include "whd_wlioctl.h" -#include "whd_buffer_api.h" -#include "cybsp_wifi.h" -#include "emac_eapol.h" -#include "cy_result.h" - -#define NULL_MAC(a) ( ( ( ( (unsigned char *)a )[0] ) == 0 ) && \ - ( ( ( (unsigned char *)a )[1] ) == 0 ) && \ - ( ( ( (unsigned char *)a )[2] ) == 0 ) && \ - ( ( ( (unsigned char *)a )[3] ) == 0 ) && \ - ( ( ( (unsigned char *)a )[4] ) == 0 ) && \ - ( ( ( (unsigned char *)a )[5] ) == 0 ) ) - -extern "C" -{ - eapol_packet_handler_t emac_eapol_packet_handler = NULL; - void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up); -} // extern "C" - -WHD_EMAC::WHD_EMAC(whd_interface_role_t role, const uint8_t *mac_addr) - : interface_type(role) -{ - if (mac_addr) { - set_hwaddr(mac_addr); - } -} - -WHD_EMAC &WHD_EMAC::get_instance(whd_interface_role_t role, const uint8_t *mac_addr) -{ - static WHD_EMAC emac_sta(WHD_STA_ROLE, mac_addr); - static WHD_EMAC emac_ap(WHD_AP_ROLE, mac_addr); - return role == WHD_AP_ROLE ? emac_ap : emac_sta; -} - -uint32_t WHD_EMAC::get_mtu_size() const -{ - return WHD_PAYLOAD_MTU; -} - -uint32_t WHD_EMAC::get_align_preference() const -{ - return 0; -} - -void WHD_EMAC::add_multicast_group(const uint8_t *addr) -{ - memcpy(multicast_addr.octet, addr, sizeof(multicast_addr.octet)); - whd_wifi_register_multicast_address(ifp, &multicast_addr); -} - -void WHD_EMAC::remove_multicast_group(const uint8_t *addr) -{ - whd_wifi_unregister_multicast_address(ifp, &multicast_addr); -} - -void WHD_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void WHD_EMAC::power_down() -{ - if (powered_up) { - powered_up = false; - whd_wifi_off(ifp); - whd_deinit(ifp); - } -} - -bool WHD_EMAC::power_up() -{ - if (!powered_up) { - cy_rslt_t res = CY_RSLT_SUCCESS; - if (ap_sta_concur && interface_type == WHD_AP_ROLE) { - WHD_EMAC &emac_prime = WHD_EMAC::get_instance(WHD_STA_ROLE); - if (NULL_MAC(unicast_addr.octet)) { - emac_prime.get_hwaddr(unicast_addr.octet); - // Generated mac will set locally administered bit 1 of first byte - unicast_addr.octet[0] |= (1 << 1); - } - // Note: This assumes that the primary interface initializes the - // wifi driver and turns on the wifi chip. - res = cybsp_wifi_init_secondary(&ifp /* Out */, &unicast_addr); - } else { - WHD_EMAC &emac_other = WHD_EMAC::get_instance(interface_type == WHD_STA_ROLE ? WHD_AP_ROLE : - WHD_STA_ROLE); - if (!emac_other.powered_up) { - res = cybsp_wifi_init_primary(&ifp /* OUT */); - } else { - ifp = emac_other.ifp; - } - } - - if (CY_RSLT_SUCCESS == res) { - drvp = cybsp_get_wifi_driver(); - powered_up = true; - if (link_state && emac_link_state_cb) { - emac_link_state_cb(link_state); - } - } else { - return false; - } - } - return true; -} - -bool WHD_EMAC::get_hwaddr(uint8_t *addr) const -{ - if (!NULL_MAC(unicast_addr.octet)) { - memcpy(addr, unicast_addr.octet, sizeof(unicast_addr.octet)); - } else { - whd_mac_t mac; - whd_result_t res = whd_wifi_get_mac_address(ifp, &mac); - MBED_ASSERT(res == WHD_SUCCESS); - memcpy(addr, mac.octet, sizeof(mac.octet)); - } - return true; -} - -void WHD_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(unicast_addr.octet, addr, sizeof(unicast_addr.octet)); -} - -uint8_t WHD_EMAC::get_hwaddr_size() const -{ - whd_mac_t mac; - return sizeof(mac.octet); -} - -void WHD_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void WHD_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void WHD_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -bool WHD_EMAC::link_out(emac_mem_buf_t *buf) -{ - uint16_t offset = 64; - whd_buffer_t buffer; - - uint16_t size = memory_manager->get_total_len(buf); - - whd_result_t res = whd_host_buffer_get(drvp, &buffer, WHD_NETWORK_TX, size + offset, WHD_TRUE); - if (res != WHD_SUCCESS) { - memory_manager->free(buf); - return true; - } - MBED_ASSERT(res == WHD_SUCCESS); - - whd_buffer_add_remove_at_front(drvp, &buffer, offset); - - void *dest = whd_buffer_get_current_piece_data_pointer(drvp, buffer); - memory_manager->copy_from_buf(dest, size, buf); - - if (activity_cb) { - activity_cb(true); - } - whd_network_send_ethernet_data(ifp, buffer); - memory_manager->free(buf); - return true; -} - -void WHD_EMAC::get_ifname(char *name, uint8_t size) const -{ - switch (interface_type) { - case WHD_STA_ROLE: - memcpy(name, "st", size); - break; - case WHD_AP_ROLE: - memcpy(name, "ap", size); - break; - default: - memcpy(name, "wh", size); - } -} - -void WHD_EMAC::set_activity_cb(mbed::Callback cb) -{ - activity_cb = cb; -} - -extern "C" -{ - - static void emac_receive_eapol_packet(whd_interface_t interface, whd_buffer_t buffer) - { - if (buffer != NULL) { - if (emac_eapol_packet_handler != NULL) { - - emac_eapol_packet_handler(interface, buffer); - } else { - whd_buffer_release(interface->whd_driver, buffer, WHD_NETWORK_RX); - } - } - } - - whd_result_t emac_register_eapol_packet_handler(eapol_packet_handler_t eapol_packet_handler) - { - - if (emac_eapol_packet_handler == NULL) { - emac_eapol_packet_handler = eapol_packet_handler; - return WHD_SUCCESS; - } - - return WHD_HANDLER_ALREADY_REGISTERED; - } - - void emac_unregister_eapol_packet_handler(void) - { - emac_eapol_packet_handler = NULL; - } - - void cy_network_process_ethernet_data(whd_interface_t ifp, whd_buffer_t buffer) - { - emac_mem_buf_t *mem_buf = NULL; - - WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role); - - if (!emac.powered_up || !emac.emac_link_input_cb) { - // ignore any trailing packets - whd_buffer_release(emac.drvp, buffer, WHD_NETWORK_RX); - return; - } - - uint8_t *data = whd_buffer_get_current_piece_data_pointer(emac.drvp, buffer); - - uint16_t size = whd_buffer_get_current_piece_size(emac.drvp, buffer); - - - if (size > WHD_ETHERNET_SIZE) { - - uint16_t ethertype; - - ethertype = (uint16_t)(data[12] << 8 | data[13]); - - if (ethertype == EAPOL_PACKET_TYPE) { - - /* pass it to the EAP layer, but do not release the packet */ - emac_receive_eapol_packet(ifp, buffer); - - } else { - mem_buf = buffer; - if (emac.activity_cb) { - emac.activity_cb(false); - } - emac.emac_link_input_cb(mem_buf); - } - } - } - - void whd_emac_wifi_link_state_changed(whd_interface_t ifp, whd_bool_t state_up) - { - WHD_EMAC &emac = WHD_EMAC::get_instance(ifp->role); - - emac.link_state = state_up; - if (emac.emac_link_state_cb) { - emac.emac_link_state_cb(state_up); - } - } - -} // extern "C" diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h deleted file mode 100644 index d50486e..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WHD_EMAC_H_ -#define WHD_EMAC_H_ - -#include "EMAC.h" -#include "EMACInterface.h" -#include "WiFiInterface.h" -#include "whd_int.h" - -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -class WHD_EMAC : public EMAC { -public: - WHD_EMAC(whd_interface_role_t itype = WHD_STA_ROLE, const uint8_t *mac_addr = NULL); - - static WHD_EMAC &get_instance(whd_interface_role_t role = WHD_STA_ROLE, const uint8_t *mac_addr = NULL); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - /** Set callback to receive EMAC activity events - * - * @param activity_cb The callback for activity events - */ - virtual void set_activity_cb(mbed::Callback activity_cb); - - emac_link_input_cb_t emac_link_input_cb = NULL; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb = NULL; - EMACMemoryManager *memory_manager; - bool powered_up = false; - bool link_state = false; - bool ap_sta_concur = false; - whd_interface_role_t interface_type; - whd_driver_t drvp = NULL; - whd_interface_t ifp = NULL; - whd_mac_t unicast_addr; - whd_mac_t multicast_addr; - mbed::Callback activity_cb; -}; - -#endif /* WHD_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp deleted file mode 100644 index 6798817..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited and affiliates. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WhdSTAInterface.h" -#include "WhdSoftAPInterface.h" -#include "whd_interface.h" - -whd_interface_shared_info_t whd_iface_shared; - -WiFiInterface *WiFiInterface::get_target_default_instance() -{ - static WhdSTAInterface wifi; - return &wifi; -} - -WhdSoftAPInterface *WhdSoftAPInterface::get_default_instance() -{ - static WhdSoftAPInterface softap; - return &softap; -} diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h deleted file mode 100644 index 73dbe30..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/interface/whd_interface.h +++ /dev/null @@ -1,51 +0,0 @@ -/* WHD implementation of NetworkInterfaceAPI - * Copyright (c) 2017-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WHD_INTERFACE_H -#define WHD_INTERFACE_H - -#include "rtos/Mutex.h" -#include "OnboardNetworkStack.h" - -/** WhdSTAInterface class - * Shared information - */ -#define IF_STATUS_ALL_IF_DOWN 0x0 -#define IF_STATUS_STA_UP 0x1 -#define IF_STATUS_SOFT_AP_UP 0x2 - -enum whd_default_interface_config -{ - DEFAULT_IF_NOT_SET, - DEFAULT_IF_STA, - DEFAULT_IF_SOFT_AP -}; - -struct whd_interface_shared_info_t { - rtos::Mutex mutex; - whd_default_interface_config default_if_cfg; - uint32_t if_status_flags; - OnboardNetworkStack::Interface *iface_sta; - OnboardNetworkStack::Interface *iface_softap; - whd_interface_shared_info_t() : default_if_cfg(DEFAULT_IF_NOT_SET), if_status_flags(IF_STATUS_ALL_IF_DOWN), - iface_sta(NULL), iface_softap(NULL) - {} -}; - -extern whd_interface_shared_info_t whd_iface_shared; - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h deleted file mode 100644 index 7d7e48f..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/network/whd_network.h +++ /dev/null @@ -1,135 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef WICED_NETWORK_H -#define WICED_NETWORK_H -#include "w_dtls_types.h" -#include "wiced_result.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -/****************************************************** - * Macros - ******************************************************/ - -#define IP_HANDLE(interface) (wiced_ip_handle[(interface) & 3]) - -/****************************************************** - * Constants - ******************************************************/ - -#define WICED_MAXIMUM_NUMBER_OF_SOCKETS_WITH_CALLBACKS (1) -#define WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS (1) - -#define SIZE_OF_ARP_ENTRY sizeof(1) - -#define IP_STACK_SIZE (2 * 1024) -#define ARP_CACHE_SIZE (6 * SIZE_OF_ARP_ENTRY) -#define DHCP_STACK_SIZE (1024) -#define WICED_PKT_SIZE (1500) -#define WICED_ANY_PORT (0) - -/****************************************************** - * Enumerations - ******************************************************/ - -typedef enum { - WICED_SOCKET_ERROR -} wiced_socket_state_t; - -/****************************************************** - * Type Definitions - ******************************************************/ -typedef struct { - uint8_t *payload; - uint16_t len; - uint16_t pktstart; -} wiced_packet_t; - - -//typedef NOOS_DUMMY wiced_tls_context_type_t; -//typedef NOOS_DUMMY wiced_tls_context_t; -//typedef NOOS_DUMMY wiced_tls_session_t; -//typedef NOOS_DUMMY wiced_tls_certificate_t; -//typedef NOOS_DUMMY wiced_tls_endpoint_type_t; -typedef void *NOOS_TCP_SOCKET; - -/****************************************************** - * Structures - ******************************************************/ - -typedef struct wiced_tcp_socket_struct wiced_tcp_socket_t; -typedef struct wiced_udp_socket_struct wiced_udp_socket_t; - -typedef wiced_result_t (*wiced_tcp_socket_callback_t)(wiced_tcp_socket_t *socket, void *arg); -typedef wiced_result_t (*wiced_udp_socket_callback_t)(wiced_udp_socket_t *socket, void *arg); - -struct wiced_udp_socket_struct { - wiced_dtls_context_t *dtls_context; - struct { - wiced_tcp_socket_callback_t disconnect; - wiced_tcp_socket_callback_t receive; - wiced_tcp_socket_callback_t connect; - } callbacks; - void *callback_arg; -}; - -struct wiced_tcp_socket_struct { - NOOS_TCP_SOCKET socket; - wiced_tls_context_t *tls_context; - wiced_bool_t context_malloced; - struct { - wiced_tcp_socket_callback_t disconnect; - wiced_tcp_socket_callback_t receive; - wiced_tcp_socket_callback_t connect; - } callbacks; - void *callback_arg; -}; - -typedef struct { - wiced_tcp_socket_t socket[WICED_MAXIMUM_NUMBER_OF_SERVER_SOCKETS]; - int interface; - uint16_t port; - wiced_tls_identity_t *tls_identity; -} wiced_tcp_server_t; - -/****************************************************** - * Global Variables - ******************************************************/ -typedef struct { - int dummy; -} NOOS_IP; -typedef struct { - int dummy; -} NOOS_PACKET_POOL; -/* - * Note: These objects are for internal use only! - */ -extern NOOS_IP wiced_ip_handle [3]; -extern NOOS_PACKET_POOL wiced_packet_pools [2]; /* 0=TX, 1=RX */ - -/****************************************************** - * Function Declarations - ******************************************************/ - - -#ifdef __cplusplus -} /*extern "C" */ -#endif -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp deleted file mode 100644 index baf2f26..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cydhcp_server_debug.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include "CyDhcpServer.h" - -#if defined(__cplusplus) -extern "C" -{ -#endif - -typedef struct DHCP_options_table_s { - uint8_t code; - uint32_t length; /* 0x80000000 means variable */ - const char *name; -} dhcp_options_table_t; - -static dhcp_options_table_t dhcp_options_lookup_table[] = { - { 0, 0, "Pad" }, - { 1, 4, "Subnet Mask" }, - { 2, 4, "Time Offset" }, - { 3, 0, "Router" }, - { 4, 0, "Time Server" }, - { 5, 0, "Name Server" }, - { 6, 0, "Domain Server" }, - { 7, 0, "Log Server" }, - { 8, 0, "Quotes Server" }, - { 9, 0, "LPR Server" }, - { 10, 0, "Impress Server" }, - { 11, 0, "RLP Server" }, - { 12, 0, "Hostname" }, - { 13, 2, "Boot File Size" }, - { 14, 0, "Merit Dump File" }, - { 15, 0, "Domain Name" }, - { 16, 0, "Swap Server" }, - { 17, 0, "Root Path" }, - { 18, 0, "Extension File" }, - { 19, 1, "Forward On/Off" }, - { 20, 1, "SrcRte On/Off" }, - { 21, 0, "Policy Filter" }, - { 22, 2, "Max DG Assembly" }, - { 23, 1, "Default IP TTL" }, - { 24, 4, "MTU Timeout" }, - { 25, 0, "MTU Plateau" }, - { 26, 2, "MTU Interface" }, - { 27, 1, "MTU Subnet" }, - { 28, 4, "Broadcast Address" }, - { 29, 1, "Mask Discovery" }, - { 30, 1, "Mask Supplier" }, - { 31, 1, "Router Discovery" }, - { 32, 4, "Router Request" }, - { 33, 0, "Static Route" }, - { 34, 1, "Trailers" }, - { 35, 4, "ARP Timeout" }, - { 36, 1, "Ethernet" }, - { 37, 1, "Default TCP TTL" }, - { 38, 4, "Keepalive Time" }, - { 39, 1, "Keepalive Data" }, - { 40, 0, "NIS Domain" }, - { 41, 0, "NIS Servers" }, - { 42, 0, "NTP Servers" }, - { 43, 0, "Vendor Specific" }, - { 44, 0, "NETBIOS Name Srv" }, - { 45, 0, "NETBIOS Dist Srv" }, - { 46, 1, "NETBIOS Node Type" }, - { 47, 0, "NETBIOS Scope" }, - { 48, 0, "X Window Font" }, - { 49, 0, "X Window Manager" }, - { 50, 4, "Address Request" }, - { 51, 4, "Address Time" }, - { 52, 1, "Overload" }, - { 53, 1, "DHCP Msg Type" }, - { 54, 4, "DHCP Server Id" }, - { 55, 0, "Parameter List" }, - { 56, 0, "DHCP Message" }, - { 57, 2, "DHCP Max Msg Size" }, - { 58, 4, "Renewal Time" }, - { 59, 4, "Rebinding Time" }, - { 60, 0, "Class Id" }, - { 61, 0, "Client Id" }, - { 62, 0, "NetWare/IP Domain" }, - { 63, 0, "NetWare/IP Option" }, - { 64, 0, "NIS-Domain-Name" }, - { 65, 0, "NIS-Server-Addr" }, - { 66, 0, "Server-Name" }, - { 67, 0, "Bootfile-Name" }, - { 68, 0, "Home-Agent-Addrs" }, - { 69, 0, "SMTP-Server" }, - { 70, 0, "POP3-Server" }, - { 71, 0, "NNTP-Server" }, - { 72, 0, "WWW-Server" }, - { 73, 0, "Finger-Server" }, - { 74, 0, "IRC-Server" }, - { 75, 0, "StreetTalk-Server" }, - { 76, 0, "STDA-Server" }, - { 77, 0, "User-Class" }, - { 78, 0, "Directory Agent" }, - { 79, 0, "Service Scope" }, - { 80, 0, "Rapid Commit" }, - { 81, 0, "Client FQDN" }, - { 82, 0, "Relay Agent Information" }, - { 83, 0, "iSNS" }, - { 85, 0, "NDS Servers" }, - { 86, 0, "NDS Tree Name" }, - { 87, 0, "NDS Context" }, - { 88, 0x80000000, "BCMCS Controller Domain Name list" }, - { 89, 0x80000000, "BCMCS Controller IPv4 address option" }, - { 90, 0, "Authentication" }, - { 91, 0x80000000, "client-last-transaction-time option" }, - { 92, 0x80000000, "associated-ip option" }, - { 93, 0, "Client System" }, - { 94, 0, "Client NDI" }, - { 95, 0, "LDAP" }, - { 97, 0, "UUID/GUID" }, - { 98, 0, "User-Auth" }, - { 99, 0x80000000, "GEOCONF_CIVIC" }, - {100, 0, "PCode" }, - {101, 0, "TCode" }, - {109, 16, "OPTION_DHCP4O6_S46_SADDR" }, - {112, 0, "Netinfo Address" }, - {113, 0, "Netinfo Tag" }, - {114, 0, "URL" }, - {116, 0, "Auto-Config" }, - {117, 0, "Name Service Search" }, - {118, 4, "Subnet Selection Option" }, - {119, 0, "Domain Search" }, - {120, 0, "SIP Servers DHCP Option" }, - {121, 0, "Classless Static Route Option" }, - {122, 0, "CCC" }, - {123, 16, "GeoConf Option" }, - {124, 0, "V-I Vendor Class" }, - {125, 0, "V-I Vendor-Specific Information" }, - {128, 0, "Etherboot signature. 6 bytes: E4:45:74:68:00:00" }, - {129, 4, "Call Server IP address" }, - {130, 0x80000000, "Ethernet interface. Variable" }, - {131, 0, "Remote statistics server IP address" }, - {132, 0, "IEEE 802.1Q VLAN ID" }, - {133, 0, "IEEE 802.1D/p Layer 2 Priority" }, - {134, 0, "Diffserv Code Point (DSCP) for" }, - {135, 0, "HTTP Proxy for phone-specific" }, - {136, 0, "OPTION_PANA_AGENT" }, - {137, 0, "OPTION_V4_LOST" }, - {138, 0, "OPTION_CAPWAP_AC_V4" }, - {139, 0, "OPTION-IPv4_Address-MoS" }, - {140, 0, "OPTION-IPv4_FQDN-MoS" }, - {141, 0, "SIP UA Configuration Service Domains" }, - {142, 0, "OPTION-IPv4_Address-ANDSF" }, - {143, 0, "OPTION_V4_SZTP_REDIRECT" }, - {144, 16, "GeoLoc" }, - {145, 1, "FORCERENEW_NONCE_CAPABLE" }, - {146, 0, "RDNSS Selection" }, - {151, 0x80000000, "N+1 status-code" }, - {152, 4, "base-time" }, - {153, 4, "start-time-of-state" }, - {154, 4, "query-start-time" }, - {155, 4, "query-end-time" }, - {156, 1, "dhcp-state" }, - {157, 1, "data-source" }, - {158, 0x80000000, " Variable; the minimum length is 5. OPTION_V4_PCP_SERVER" }, - {159, 4, "OPTION_V4_PORTPARAMS" }, - {160, 0, "DHCP Captive-Portal" }, - {161, 0x80000000, "(variable) OPTION_MUD_URL_V4" }, - {208, 4, "PXELINUX Magic" }, - {209, 0, "Configuration File" }, - {210, 0, "Path Prefix" }, - {211, 4, "Reboot Time" }, - {212, 0x80000000, "18+ N OPTION_6RD" }, - {213, 0, "OPTION_V4_ACCESS_DOMAIN" }, - {220, 0, "Subnet Allocation Option" }, -}; - -#define isprint(c) ((c) >= 0x20 && (c) < 0x7f) -int hex_dump_print(const void *data_ptr, uint16_t length, int show_ascii) -{ - uint8_t *data = (uint8_t *)data_ptr; - uint8_t *char_ptr; - int i, count; - if ((data == NULL) || (length == 0)) { - return -1; - } - count = 0; - char_ptr = data; - while (length > 0) { - i = 0; - while ((length > 0) && (i < 16)) { - printf(" %02x", *data); - i++; - data++; - length--; - count++; - } - - if (show_ascii != 0) { - int fill = 16 - i; - /* fill in for < 16 */ - while (fill > 0) { - printf(" "); - fill--; - } - /* space between numbers and chars */ - printf(" "); - while (i > 0) { - printf("%c", (isprint(*char_ptr) ? *char_ptr : '.')); - char_ptr++; - i--; - } - } - printf("\n"); - } - return count; -} - - -void dhcp_server_print_header_info(dhcp_packet_t *header, uint32_t datalen, const char *title) -{ - uint8_t *ptr; - if (title != NULL) { - printf("%s:\n", title); - } - - printf("Opcode :%2d : %s\n", header->Opcode, (header->Opcode == 1) ? "Request" : (header->Opcode == 2) ? "Reply" : "Unknown"); - printf("HwType :%2d : %s\n", header->HwType, (header->HwType == 1) ? "Ethernet" : "Unknown"); - printf("HwLength : : %d\n", header->HwLen); - printf("Hops : : %d\n", header->Hops); - printf("TransactionId : : 0x%lx\n", header->TransactionId); - printf("Elapsed time : : %d\n", header->SecsElapsed); - printf("Flags : : 0x%08x\n", header->Flags); - uint8_t *ip_ptr = (uint8_t *)&header->ClientIpAddr; - printf("from client IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); - ip_ptr = (uint8_t *)&header->YourIpAddr; - printf("from us YOUR IP: : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); - ip_ptr = (uint8_t *)&header->ServerIpAddr; - printf("DHCP server IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); - ip_ptr = (uint8_t *)&header->GatewayIpAddr; - printf("gateway IP : : %d.%d.%d.%d\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); - - printf("Client MAC : :"); - hex_dump_print(header->ClientHwAddr, 16, 0); - ip_ptr = (uint8_t *)&header->MagicCookie; - printf("Magic : : %2x %2x %2x %2x\n", ip_ptr[0], ip_ptr[1], ip_ptr[2], ip_ptr[3]); - - printf("Options :\n"); - ptr = (uint8_t *)header->Options; - printf("Hex Dump:\n"); - hex_dump_print(ptr, 64, 1); - printf("\n"); - - while ((ptr != NULL) && (*ptr != DHCP_END_OPTION_CODE) && ((uint32_t)(ptr - &header->Options[0]) < datalen)) { - int len; - switch (*ptr) { - case DHCP_SUBNETMASK_OPTION_CODE: // (1) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d SUBNET MASK : ", DHCP_SUBNETMASK_OPTION_CODE, len); - hex_dump_print(ptr, len, 1); - ptr += len; - break; - case DHCP_ROUTER_OPTION_CODE: // (3) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d ROUTER : ", DHCP_ROUTER_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_DNS_SERVER_OPTION_CODE: // (6) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d DNS SERVER : ", DHCP_DNS_SERVER_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_HOST_NAME_OPTION_CODE: - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d HOST NAME : ", DHCP_HOST_NAME_OPTION_CODE, len); - hex_dump_print(ptr, len, 1); - ptr += len; - break; - case DHCP_MTU_OPTION_CODE: // (26) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d MTU : ", DHCP_MTU_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE: // (50) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d REQUESTED IP : ", DHCP_REQUESTED_IP_ADDRESS_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_LEASETIME_OPTION_CODE: // (51) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d LEASE TIME : ", DHCP_LEASETIME_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_MESSAGETYPE_OPTION_CODE: { // (53) - ptr++; - len = *ptr++; - int code = *ptr; - printf(" Code:%d Length:%d MESSAGE : ", DHCP_MESSAGETYPE_OPTION_CODE, len); - switch (code) { - case 1: - printf(" %d -- DHCP DISCOVER\n", code); - break; - case 2: - printf(" %d -- DHCP OFFER\n", code); - break; - case 3: - printf(" %d -- DHCP REQUEST\n", code); - break; - case 4: - printf(" %d -- DHCP DECLINE\n", code); - break; - case 5: - printf(" %d -- DHCP ACK\n", code); - break; - case 6: - printf(" %d -- DHCP NACK\n", code); - break; - case 7: - printf(" %d -- DHCP RELEASE\n", code); - break; - case 8: - printf(" %d -- DHCP INFORM\n", code); - break; - default: - printf(" %d -- INVALID\n", code); - break; - } - ptr += len; - break; - } - case DHCP_SERVER_IDENTIFIER_OPTION_CODE: // (54) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d SERVER ID : ", DHCP_SERVER_IDENTIFIER_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - ptr += len; - break; - case DHCP_PARAM_REQUEST_LIST_OPTION_CODE: -// 9.8. Parameter Request List -// -// This option is used by a DHCP client to request values for specified -// configuration parameters. The list of requested parameters is -// specified as n octets, where each octet is a valid DHCP option code -// as defined in this document. -// -// The client MAY list the options in order of preference. The DHCP -// server is not required to return the options in the requested order, -// but MUST try to insert the requested options in the order requested -// by the client. -// -// The code for this option is 55. Its minimum length is 1. -// -// Code Len Option Codes -// +-----+-----+-----+-----+--- -// | 55 | n | c1 | c2 | ... -// +-----+-----+-----+-----+--- - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d PARAM REQ : ", DHCP_PARAM_REQUEST_LIST_OPTION_CODE, len); - hex_dump_print(ptr, len, 0); - { - int i; - for (i = 0; i < len; i++) { - uint8_t sub_code; - sub_code = *ptr++; - - uint32_t lookup_index; - uint32_t max_lookup = (sizeof(dhcp_options_lookup_table) / sizeof(dhcp_options_lookup_table[0])); - for (lookup_index = 0; lookup_index < max_lookup; lookup_index++) { - if (dhcp_options_lookup_table[lookup_index].code == sub_code) { - uint32_t length = dhcp_options_lookup_table[lookup_index].length; - if (length != 0) { - /* length is variable, in the length field ? */ - length = *ptr; - } - printf(" Code:%3d : %s\n", dhcp_options_lookup_table[lookup_index].code, dhcp_options_lookup_table[lookup_index].name); - break; - } - } - if (lookup_index >= max_lookup) { - printf(" Code:%3d : UNKNOWN\n", dhcp_options_lookup_table[lookup_index].code); - } - } - } - break; - case DHCP_WPAD_OPTION_CODE: // (252) - ptr++; - len = *ptr++; - printf(" Code:%d Length:%d WPAD : ", DHCP_WPAD_OPTION_CODE, len); - hex_dump_print(ptr, len, 1); - ptr += len; - break; - - default: - ptr++; - break; - } - } -} - -#if defined(__cplusplus) -} -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c deleted file mode 100644 index 9a92391..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "cynetwork_utils.h" - -uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length) -{ - uint8_t digits_left; - char buffer[] = "0000000000"; - - if (output == NULL) { - return 0; - } - - max_length = (uint8_t) MIN(max_length, sizeof(buffer)); - digits_left = max_length; - while ((value != 0) && (digits_left != 0)) { - --digits_left; - buffer[digits_left] = (char)((value % 10) + '0'); - value = value / 10; - } - - digits_left = (uint8_t) MIN((max_length - min_length), digits_left); - memcpy(output, &buffer[digits_left], (size_t)(max_length - digits_left)); - - /* Add terminating null */ - output[(max_length - digits_left)] = '\x00'; - - return (uint8_t)(max_length - digits_left); -} - -void ipv4_to_string(char buffer[16], uint32_t ipv4_address) -{ - uint8_t *ip = (uint8_t *)&ipv4_address; - - /* unsigned_to_decimal_string() null-terminates the string - * Save the original last character and replace it */ - char last_char = buffer[16]; - unsigned_to_decimal_string(ip[0], &buffer[0], 3, 3); - buffer[3] = '.'; - unsigned_to_decimal_string(ip[1], &buffer[4], 3, 3); - buffer[7] = '.'; - unsigned_to_decimal_string(ip[2], &buffer[8], 3, 3); - buffer[11] = '.'; - unsigned_to_decimal_string(ip[3], &buffer[12], 3, 3); - buffer[16] = last_char; -} - -uint32_t string_to_ipv4(const char *buffer) -{ - uint32_t temp = 0; - int char_count = 0; - const char *ptr = buffer; - - while ((ptr != NULL) && (*ptr != 0) && (char_count++ < 16)) { - uint8_t byte = 0; - while ((*ptr != 0) && (*ptr != '.') && (char_count++ < 16)) { - byte *= 10; - if ((*ptr >= '0') && (*ptr <= '9')) { - byte += (*ptr - '0'); - } else { - break; - } - ptr++; - } - temp <<= 8; - temp |= byte; - if (*ptr == '.') { - ptr++; /* skip '.' */ - } - } - return temp; -} - diff --git a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h b/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h deleted file mode 100644 index 0a7bdc0..0000000 --- a/features/netsocket/emac-drivers/TARGET_Cypress/COMPONENT_WHD/utils/cynetwork_utils.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2018-2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef MIN -extern int MIN(/*@sef@*/ int x, /*@sef@*/ int y); /* LINT : This tells lint that the parameter must be side-effect free. i.e. evaluation does not change any values (since it is being evaulated more than once */ -#define MIN(x,y) ((x) < (y) ? (x) : (y)) -#endif /* ifndef MIN */ - -#define FX_IPTYPE_IPV4 (0) -#define FX_IPTYPE_IPV6 (1) - -typedef union { - uint32_t addr; - uint8_t addrs[4]; -} cy_ip_addr_v4_t; - -typedef struct { - uint32_t addr[4]; -} cy_ip_addr_v6_t; - -typedef struct { - uint8_t type; - union { - cy_ip_addr_v4_t addrv4; - cy_ip_addr_v6_t addrv6; - }; -} cy_ip_addr_t; - -/** - * Structure for storing a MAC address (Wi-Fi Media Access Control address). - */ -typedef struct { - uint8_t octet[6]; /**< Unique 6-byte MAC address */ -} cy_mac_addr_t; - -/** - * Converts a unsigned long int to a decimal string - * - * @param value[in] : The unsigned long to be converted - * @param output[out] : The buffer which will receive the decimal string - * @param min_length[in] : the minimum number of characters to output (zero padding will apply if required). - * @param max_length[in] : the maximum number of characters to output (up to 10 ). There must be space for terminating NULL. - * - * @note: A terminating NULL is added. Wnsure that there is space in the buffer for this. - * - * @return the number of characters returned (excluding terminating null) - * - */ -uint8_t unsigned_to_decimal_string(uint32_t value, char *output, uint8_t min_length, uint8_t max_length); - -/** - * Convert a IPv4 address to a string - * - * @note: String is 16 bytes including terminating null - * - * @param[out] buffer : Buffer which will recieve the IPv4 string - * @param[in] ipv4_address : IPv4 address to convert - */ -void ipv4_to_string(char buffer[16], uint32_t ipv4_address); - -/** - * Convert a IPv4 address to a string - * - * @note: String is 16 bytes including terminating null - * - * @param[in] buffer : Buffer which has the IPv4 string - * @return ipv4_address (0 on failure) - */ -uint32_t string_to_ipv4(const char *buffer); - -#if defined(__cplusplus) -} -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c deleted file mode 100644 index bdd51be..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K64F/hardware_init_MK64F12.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fsl_port.h" -#include "fsl_sysmpu.h" - -/* Initialize the region 1, master 0, 1, 2, 3 - core access rights supervisior r/w/x , user r/w/x. */ -sysmpu_rwxrights_master_access_control_t right = -{ - kSYSMPU_SupervisorEqualToUsermode, - kSYSMPU_UserReadWriteExecute, -#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER - false, -#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ -}; - -/******************************************************************************* - * Code - ******************************************************************************/ -void kinetis_init_eth_hardware(void) -{ - port_pin_config_t configENET = {0}; - sysmpu_region_config_t regConfig; - sysmpu_config_t config; - - memset(®Config, 0, sizeof(sysmpu_region_config_t)); - memset(&config, 0, sizeof(sysmpu_config_t)); - - regConfig.regionNum = 1; - regConfig.startAddress = 0U; - regConfig.endAddress = 0xFFFFFFFFU; - regConfig.accessRights1[0] = right; - regConfig.accessRights1[1] = right; - regConfig.accessRights1[2] = right; - regConfig.accessRights1[3] = right; - -#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER - regConfig.processIdentifier = 1U; - regConfig.processIdMask = 0U; -#endif - - config.regionConfig = regConfig; - SYSMPU_Init(SYSMPU, &config); - - CLOCK_EnableClock(kCLOCK_PortC); - CLOCK_EnableClock(kCLOCK_PortB); - /* Affects PORTC_PCR16 register */ - PORT_SetPinMux(PORTC, 16u, kPORT_MuxAlt4); - /* Affects PORTC_PCR17 register */ - PORT_SetPinMux(PORTC, 17u, kPORT_MuxAlt4); - /* Affects PORTC_PCR18 register */ - PORT_SetPinMux(PORTC, 18u, kPORT_MuxAlt4); - /* Affects PORTC_PCR19 register */ - PORT_SetPinMux(PORTC, 19u, kPORT_MuxAlt4); - /* Affects PORTB_PCR1 register */ - PORT_SetPinMux(PORTB, 1u, kPORT_MuxAlt4); - - configENET.openDrainEnable = kPORT_OpenDrainEnable; - configENET.mux = kPORT_MuxAlt4; - configENET.pullSelect = kPORT_PullUp; - /* Ungate the port clock */ - CLOCK_EnableClock(kCLOCK_PortA); - /* Affects PORTB_PCR0 register */ - PORT_SetPinConfig(PORTB, 0u, &configENET); - - /* Affects PORTA_PCR13 register */ - PORT_SetPinMux(PORTA, 13u, kPORT_MuxAlt4); - /* Affects PORTA_PCR12 register */ - PORT_SetPinMux(PORTA, 12u, kPORT_MuxAlt4); - /* Affects PORTA_PCR14 register */ - PORT_SetPinMux(PORTA, 14u, kPORT_MuxAlt4); - /* Affects PORTA_PCR5 register */ - PORT_SetPinMux(PORTA, 5u, kPORT_MuxAlt4); - /* Affects PORTA_PCR16 register */ - PORT_SetPinMux(PORTA, 16u, kPORT_MuxAlt4); - /* Affects PORTA_PCR17 register */ - PORT_SetPinMux(PORTA, 17u, kPORT_MuxAlt4); - /* Affects PORTA_PCR15 register */ - PORT_SetPinMux(PORTA, 15u, kPORT_MuxAlt4); - /* Affects PORTA_PCR28 register */ - PORT_SetPinMux(PORTA, 28u, kPORT_MuxAlt4); - - /* Select the Ethernet timestamp clock source */ - CLOCK_SetEnetTime0Clock(0x2); -} - -/******************************************************************************* - * EOF - ******************************************************************************/ - - diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c deleted file mode 100644 index d891fb3..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/TARGET_K66F/hardware_init_MK66F18.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2016, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fsl_port.h" -#include "fsl_sysmpu.h" - -/* Initialize the region 1, master 0, 1, 2, 3 - core access rights supervisior r/w/x , user r/w/x. */ -sysmpu_rwxrights_master_access_control_t right = -{ - kSYSMPU_SupervisorEqualToUsermode, - kSYSMPU_UserReadWriteExecute, -#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER - false, -#endif /* FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER */ -}; - -/******************************************************************************* - * Code - ******************************************************************************/ -void kinetis_init_eth_hardware(void) -{ - port_pin_config_t configENET = {0}; - sysmpu_region_config_t regConfig; - sysmpu_config_t config; - - memset(®Config, 0, sizeof(sysmpu_region_config_t)); - memset(&config, 0, sizeof(sysmpu_config_t)); - - regConfig.regionNum = 1; - regConfig.startAddress = 0U; - regConfig.endAddress = 0xFFFFFFFFU; - regConfig.accessRights1[0] = right; - regConfig.accessRights1[1] = right; - regConfig.accessRights1[2] = right; - regConfig.accessRights1[3] = right; - -#if FSL_FEATURE_SYSMPU_HAS_PROCESS_IDENTIFIER - regConfig.processIdentifier = 1U; - regConfig.processIdMask = 0U; -#endif - - config.regionConfig = regConfig; - SYSMPU_Init(SYSMPU, &config); - - /* Ungate the port clock */ - CLOCK_EnableClock(kCLOCK_PortA); - CLOCK_EnableClock(kCLOCK_PortB); - CLOCK_EnableClock(kCLOCK_PortE); - - /* Affects PORTE_PCR26 register, configured as ENET_1588 CLKIN */ - PORT_SetPinMux(PORTE, 26u, kPORT_MuxAlt2); - /* Affects PORTB_PCR1 register */ - PORT_SetPinMux(PORTB, 1u, kPORT_MuxAlt4); - - configENET.openDrainEnable = kPORT_OpenDrainEnable; - configENET.mux = kPORT_MuxAlt4; - configENET.pullSelect = kPORT_PullUp; - /* Affects PORTB_PCR0 register */ - PORT_SetPinConfig(PORTB, 0u, &configENET); - - /* Affects PORTA_PCR13 register */ - PORT_SetPinMux(PORTA, 13u, kPORT_MuxAlt4); - /* Affects PORTA_PCR12 register */ - PORT_SetPinMux(PORTA, 12u, kPORT_MuxAlt4); - /* Affects PORTA_PCR14 register */ - PORT_SetPinMux(PORTA, 14u, kPORT_MuxAlt4); - /* Affects PORTA_PCR5 register */ - PORT_SetPinMux(PORTA, 5u, kPORT_MuxAlt4); - /* Affects PORTA_PCR16 register */ - PORT_SetPinMux(PORTA, 16u, kPORT_MuxAlt4); - /* Affects PORTA_PCR17 register */ - PORT_SetPinMux(PORTA, 17u, kPORT_MuxAlt4); - /* Affects PORTA_PCR15 register */ - PORT_SetPinMux(PORTA, 15u, kPORT_MuxAlt4); - - /* Set RMII clock src. */ - CLOCK_SetRmii0Clock(1U); - - /* Select the Ethernet timestamp clock source */ - CLOCK_SetEnetTime0Clock(0x2); -} - -/******************************************************************************* - * EOF - ******************************************************************************/ - - diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.cpp b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.cpp deleted file mode 100644 index 7485284..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * Copyright (c) 2017 ARM Limited - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -#include "fsl_phy.h" - -#include "kinetis_emac_config.h" -#include "kinetis_emac.h" -#include "mbed_power_mgmt.h" - -using namespace std::chrono; - -enet_handle_t g_handle; -// TX Buffer descriptors -uint8_t *tx_desc_start_addr; -// RX Buffer descriptors -uint8_t *rx_desc_start_addr; -// RX packet buffer pointers -emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; -// TX packet buffer pointers -emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; -// RX packet payload pointers -uint32_t *rx_ptr[ENET_RX_RING_LEN]; - -/******************************************************************************** - * Internal data - ********************************************************************************/ -#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) -#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) - -extern "C" void kinetis_init_eth_hardware(void); - -/* \brief Flags for worker thread */ -#define FLAG_TX 1 -#define FLAG_RX 2 - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityNormal) - -#define PHY_TASK_PERIOD 200ms - -Kinetis_EMAC::Kinetis_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} -/******************************************************************************** - * Buffer management - ********************************************************************************/ -/* - * This function will queue a new receive buffer - */ -static void update_read_buffer(uint8_t *buf) -{ - if (buf != NULL) { - g_handle.rxBdCurrent->buffer = buf; - } - - /* Clears status. */ - g_handle.rxBdCurrent->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; - - /* Sets the receive buffer descriptor with the empty flag. */ - g_handle.rxBdCurrent->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - - /* Increases the buffer descriptor to the next one. */ - if (g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) { - g_handle.rxBdCurrent = g_handle.rxBdBase; - } else { - g_handle.rxBdCurrent++; - } - - /* Actives the receive buffer descriptor. */ - ENET->RDAR = ENET_RDAR_RDAR_MASK; -} - -/** \brief Free TX buffers that are complete - */ -void Kinetis_EMAC::tx_reclaim() -{ - /* Get exclusive access */ - TXLockMutex.lock(); - - // Traverse all descriptors, looking for the ones modified by the uDMA - while ((tx_consume_index != tx_produce_index) && - (!(g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { - memory_manager->free(tx_buff[tx_consume_index % ENET_TX_RING_LEN]); - if (g_handle.txBdDirty->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { - g_handle.txBdDirty = g_handle.txBdBase; - } else { - g_handle.txBdDirty++; - } - - tx_consume_index += 1; - xTXDCountSem.release(); - } - - /* Restore access */ - TXLockMutex.unlock(); -} - -/** \brief Ethernet receive interrupt handler - * - * This function handles the receive interrupt. - */ -void Kinetis_EMAC::rx_isr() -{ - if (thread) { - osThreadFlagsSet(thread, FLAG_RX); - } -} - -void Kinetis_EMAC::tx_isr() -{ - osThreadFlagsSet(thread, FLAG_TX); -} - -void Kinetis_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) -{ - Kinetis_EMAC *enet = static_cast(param); - switch (event) { - case kENET_RxEvent: - enet->rx_isr(); - break; - case kENET_TxEvent: - enet->tx_isr(); - break; - default: - break; - } -} - - -/** \brief Low level init of the MAC and PHY. - */ -bool Kinetis_EMAC::low_level_init_successful() -{ - uint8_t i; - uint32_t sysClock; - phy_speed_t phy_speed; - phy_duplex_t phy_duplex; - uint32_t phyAddr = 0; - enet_config_t config; - - // Allocate RX descriptors - rx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_rx_bd_struct_t) * ENET_RX_RING_LEN + ENET_BUFF_ALIGNMENT); - if (!rx_desc_start_addr) { - return false; - } - - // Allocate TX descriptors - tx_desc_start_addr = (uint8_t *)calloc(1, sizeof(enet_tx_bd_struct_t) * ENET_TX_RING_LEN + ENET_BUFF_ALIGNMENT); - if (!tx_desc_start_addr) { - return false; - } - - rx_desc_start_addr = (uint8_t *)ENET_ALIGN(rx_desc_start_addr, ENET_BUFF_ALIGNMENT); - tx_desc_start_addr = (uint8_t *)ENET_ALIGN(tx_desc_start_addr, ENET_BUFF_ALIGNMENT); - - /* Create buffers for each receive BD */ - for (i = 0; i < ENET_RX_RING_LEN; i++) { - rx_buff[i] = memory_manager->alloc_heap(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); - if (NULL == rx_buff[i]) { - return false; - } - - rx_ptr[i] = (uint32_t *)memory_manager->get_ptr(rx_buff[i]); - } - - tx_consume_index = tx_produce_index = 0; - - /* prepare the buffer configuration. */ - enet_buffer_config_t buffCfg = { - ENET_RX_RING_LEN, - ENET_TX_RING_LEN, - ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), - 0, - (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, - (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, - (uint8_t *) &rx_ptr, - NULL, - }; - - kinetis_init_eth_hardware(); - - sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); - - ENET_GetDefaultConfig(&config); - - if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) { - return false; - } - - /* Get link information from PHY */ - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); - /* Change the MII speed and duplex for actual link status. */ - config.miiSpeed = (enet_mii_speed_t)phy_speed; - config.miiDuplex = (enet_mii_duplex_t)phy_duplex; - config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; - config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; - config.macSpecialConfig = kENET_ControlFlowControlEnable; - config.txAccelerConfig = 0; - config.rxAccelerConfig = kENET_RxAccelMacCheckEnabled; - ENET_Init(ENET, &g_handle, &config, &buffCfg, hwaddr, sysClock); - - ENET_SetCallback(&g_handle, &Kinetis_EMAC::ethernet_callback, this); - ENET_ActiveRead(ENET); - - return true; -} - -/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. - * - * \param[in] idx index of packet to be read - * \return a emac_mem_buf_t filled with the received packet (including MAC header) - */ -emac_mem_buf_t *Kinetis_EMAC::low_level_input(int idx) -{ - volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent; - emac_mem_buf_t *p = NULL; - emac_mem_buf_t *temp_rxbuf = NULL; - uint32_t length = 0; - const uint16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | - ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; - -#ifdef LOCK_RX_THREAD - /* Get exclusive access */ - TXLockMutex.lock(); -#endif - - /* Determine if a frame has been received */ - if ((bdPtr->control & err_mask) != 0) { - /* Re-use the same buffer in case of error */ - update_read_buffer(NULL); - } else { - /* A packet is waiting, get length */ - length = bdPtr->length; - - /* Zero-copy */ - p = rx_buff[idx]; - memory_manager->set_len(p, length); - - /* Attempt to queue new buffer */ - temp_rxbuf = memory_manager->alloc_heap(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT); - if (NULL == temp_rxbuf) { - /* Re-queue the same buffer */ - update_read_buffer(NULL); - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - - return NULL; - } - - rx_buff[idx] = temp_rxbuf; - rx_ptr[idx] = (uint32_t *)memory_manager->get_ptr(rx_buff[idx]); - - update_read_buffer((uint8_t *)rx_ptr[idx]); - } - -#ifdef LOCK_RX_THREAD - osMutexRelease(TXLockMutex); -#endif - - return p; -} - -/** \brief Attempt to read a packet from the EMAC interface. - * - * \param[in] idx index of packet to be read - */ -void Kinetis_EMAC::input(int idx) -{ - emac_mem_buf_t *p; - - /* move received packet into a new buf */ - p = low_level_input(idx); - if (p == NULL) { - return; - } - - emac_link_input_cb(p); -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void Kinetis_EMAC::thread_function(void *pvParameters) -{ - struct Kinetis_EMAC *kinetis_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); - - MBED_ASSERT(!(flags & osFlagsError)); - - if (flags & FLAG_RX) { - kinetis_enet->packet_rx(); - } - - if (flags & FLAG_TX) { - kinetis_enet->packet_tx(); - } - } -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the LWIP core. - */ -void Kinetis_EMAC::packet_rx() -{ - static int idx = 0; - - while ((g_handle.rxBdCurrent->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { - input(idx); - idx = (idx + 1) % ENET_RX_RING_LEN; - } -} - -/** \brief Transmit cleanup task - * - * This task is called when a transmit interrupt occurs and - * reclaims the buffer and descriptor used for the packet once - * the packet has been transferred. - */ -void Kinetis_EMAC::packet_tx() -{ - tx_reclaim(); -} - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent - */ -bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf) -{ - // If buffer is chained or not aligned then make a contiguous aligned copy of it - if (memory_manager->get_next(buf) || - reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { - emac_mem_buf_t *copy_buf; - copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); - if (NULL == copy_buf) { - memory_manager->free(buf); - return false; - } - - // Copy to new buffer and free original - memory_manager->copy(copy_buf, buf); - memory_manager->free(buf); - buf = copy_buf; - } - - /* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */ - if (!xTXDCountSem.try_acquire_for(10)) { - memory_manager->free(buf); - return false; - } - - /* Get exclusive access */ - TXLockMutex.lock(); - - /* Save the buffer so that it can be freed when transmit is done */ - tx_buff[tx_produce_index % ENET_TX_RING_LEN] = buf; - tx_produce_index += 1; - - /* Setup transfers */ - g_handle.txBdCurrent->buffer = static_cast(memory_manager->get_ptr(buf)); - g_handle.txBdCurrent->length = memory_manager->get_len(buf); - g_handle.txBdCurrent->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); - - /* Increase the buffer descriptor address. */ - if (g_handle.txBdCurrent->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { - g_handle.txBdCurrent = g_handle.txBdBase; - } else { - g_handle.txBdCurrent++; - } - - /* Active the transmit buffer descriptor. */ - ENET->TDAR = ENET_TDAR_TDAR_MASK; - - /* Restore access */ - TXLockMutex.unlock(); - - return true; -} - -/******************************************************************************* - * PHY task: monitor link -*******************************************************************************/ - -#define STATE_UNKNOWN (-1) -#define STATE_LINK_DOWN (0) -#define STATE_LINK_UP (1) - -void Kinetis_EMAC::phy_task() -{ - uint32_t phyAddr = 0; - - // Get current status - PHY_STATE crt_state; - bool connection_status; - PHY_GetLinkStatus(ENET, phyAddr, &connection_status); - - if (connection_status) { - crt_state.connected = STATE_LINK_UP; - } else { - crt_state.connected = STATE_LINK_DOWN; - } - - if (crt_state.connected == STATE_LINK_UP) { - if (prev_state.connected != STATE_LINK_UP) { - PHY_AutoNegotiation(ENET, phyAddr); - } - - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); - - if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) { - /* Poke the registers*/ - ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex); - } - } - - // Compare with previous state - if (crt_state.connected != prev_state.connected && emac_link_state_cb) { - emac_link_state_cb(crt_state.connected); - } - - prev_state = crt_state; -} - -bool Kinetis_EMAC::power_up() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - // Can't enter deep sleep as long as Ethernet is active - sleep_manager_lock_deep_sleep(); - - /* Worker thread */ - thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); - - /* Trigger thread to deal with any RX packets that arrived before thread was started */ - rx_isr(); - - /* PHY monitoring task */ - prev_state.connected = STATE_LINK_DOWN; - prev_state.speed = (phy_speed_t)STATE_UNKNOWN; - prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; - - mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &Kinetis_EMAC::phy_task)); - - return true; -} - -uint32_t Kinetis_EMAC::get_mtu_size() const -{ - return KINETIS_ETH_MTU_SIZE; -} - -uint32_t Kinetis_EMAC::get_align_preference() const -{ - return ENET_BUFF_ALIGNMENT; -} - -void Kinetis_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, KINETIS_ETH_IF_NAME, (size < sizeof(KINETIS_ETH_IF_NAME)) ? size : sizeof(KINETIS_ETH_IF_NAME)); -} - -uint8_t Kinetis_EMAC::get_hwaddr_size() const -{ - return KINETIS_HWADDR_SIZE; -} - -bool Kinetis_EMAC::get_hwaddr(uint8_t *addr) const -{ - return false; -} - -void Kinetis_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, sizeof hwaddr); - ENET_SetMacAddr(ENET, const_cast(addr)); -} - -void Kinetis_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void Kinetis_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void Kinetis_EMAC::add_multicast_group(const uint8_t *addr) -{ - ENET_AddMulticastGroup(ENET, const_cast(addr)); -} - -void Kinetis_EMAC::remove_multicast_group(const uint8_t *addr) -{ - // ENET HAL doesn't reference count - ENET_LeaveMulticastGroup just maps - // address to filter bit, and clears that bit, even if shared by other - // addresses. So don't attempt anything for now. -} - -void Kinetis_EMAC::set_all_multicast(bool all) -{ - if (all) { - ENET->GAUR = 0xFFFFFFFFu; - ENET->GALR = 0xFFFFFFFFu; - } -} - -void Kinetis_EMAC::power_down() -{ - // Ethernet went down, can enter deep sleep - sleep_manager_unlock_deep_sleep(); -} - -void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - - -Kinetis_EMAC &Kinetis_EMAC::get_instance() -{ - static Kinetis_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return Kinetis_EMAC::get_instance(); -} - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */ - diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.h b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.h deleted file mode 100644 index 82b588b..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac.h +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef KINETIS_EMAC_H_ -#define KINETIS_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -class Kinetis_EMAC : public EMAC { -public: - Kinetis_EMAC(); - - static Kinetis_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - bool low_level_init_successful(); - void rx_isr(); - void tx_isr(); - void packet_rx(); - void packet_tx(); - void tx_reclaim(); - void input(int idx); - emac_mem_buf_t *low_level_input(int idx); - static void thread_function(void* pvParameters); - void phy_task(); - static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param); - - mbed_rtos_storage_thread_t thread_cb; - osThreadId_t thread; /**< Processing thread */ - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ - uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - int phy_task_handle; /**< Handle for phy task event */ - struct PHY_STATE { - int connected; - phy_speed_t speed; - phy_duplex_t duplex; - }; - PHY_STATE prev_state; - uint8_t hwaddr[KINETIS_HWADDR_SIZE]; -}; - -#endif /* KINETIS_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac_config.h b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac_config.h deleted file mode 100644 index a56fe41..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/kinetis_emac_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef KINETIS_EMAC_CONFIG_H__ -#define KINETIS_EMAC_CONFIG_H__ - -#include "fsl_enet.h" - -#define ENET_RX_RING_LEN MBED_CONF_KINETIS_EMAC_RX_RING_LEN -#define ENET_TX_RING_LEN MBED_CONF_KINETIS_EMAC_TX_RING_LEN - -#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame - -#define KINETIS_HWADDR_SIZE (6) - -#define KINETIS_ETH_MTU_SIZE 1500 -#define KINETIS_ETH_IF_NAME "en" - -#define THREAD_STACKSIZE 512 - -#endif // #define KINETIS_EMAC_CONFIG_H__ - diff --git a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/mbed_lib.json deleted file mode 100644 index 102de42..0000000 --- a/features/netsocket/emac-drivers/TARGET_Freescale_EMAC/mbed_lib.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "kinetis-emac", - "config": { - "rx-ring-len": 2, - "tx-ring-len": 1 - } -} diff --git a/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c b/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c deleted file mode 100644 index 4c25fab..0000000 --- a/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F30X/gd32f3_eth_init.c +++ /dev/null @@ -1,79 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 GigaDevice Semiconductor Inc. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "gd32f30x.h" - -/** - * Initializes the HW pin for enet - * - */ -void enet_bsp_init(void) -{ - /* Enable GPIOs clocks */ - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOB); - rcu_periph_clock_enable(RCU_GPIOC); - rcu_periph_clock_enable(RCU_AF); - - gpio_para_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8); - rcu_pll2_config(RCU_PLL2_MUL10); - rcu_osci_on(RCU_PLL2_CK); - rcu_osci_stab_wait(RCU_PLL2_CK); - rcu_ckout0_config(RCU_CKOUT0SRC_CKPLL2); - gpio_ethernet_phy_select(GPIO_ENET_PHY_RMII); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_TX_EN --------------------> PB11 - RMII_MII_TXD0 ---------------------> PB12 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* PA1: ETH_RMII_REF_CLK */ - gpio_para_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_1); - /* PA2: ETH_MDIO */ - gpio_para_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2); - /* PA7: ETH_RMII_CRS_DV */ - gpio_para_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_7); - - /* PB11: ETH_RMII_TX_EN */ - gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); - /* PB12: ETH_RMII_TXD0 */ - gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); - /* PB13: ETH_RMII_TXD1 */ - gpio_para_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); - - /* PC1: ETH_MDC */ - gpio_para_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1); - /* PC4: ETH_RMII_RXD0 */ - gpio_para_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_4); - /* PC5: ETH_RMII_RXD1 */ - gpio_para_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_MAX, GPIO_PIN_5); - - /* Enable the Ethernet global Interrupt */ - nvic_irq_enable(ENET_IRQn, 0x7, 0); - - /* Enable ETHERNET clock */ - rcu_periph_clock_enable(RCU_ENET); - rcu_periph_clock_enable(RCU_ENETTX); - rcu_periph_clock_enable(RCU_ENETRX); -} diff --git a/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c b/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c deleted file mode 100644 index 1de087f..0000000 --- a/features/netsocket/emac-drivers/TARGET_GD_EMAC/TARGET_GD32F4XX/gd32f4_eth_init.c +++ /dev/null @@ -1,102 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 GigaDevice Semiconductor Inc. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "gd32f4xx.h" - -/** - * Initializes the HW pin for enet - * - */ -void enet_bsp_init(void) -{ - /* enable GPIOs clocks */ - rcu_periph_clock_enable(RCU_GPIOA); - rcu_periph_clock_enable(RCU_GPIOB); - rcu_periph_clock_enable(RCU_GPIOC); - - /* enable SYSCFG clock */ - rcu_periph_clock_enable(RCU_SYSCFG); - syscfg_enet_phy_interface_config(SYSCFG_ENET_PHY_RMII); - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_TX_EN --------------------> PB11 - RMII_MII_TXD0 ---------------------> PB12 - RMII_MII_TXD1 ---------------------> PB13 - */ - - /* PA1: ETH_RMII_REF_CLK */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_1); - - /* PA2: ETH_MDIO */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_2); - - /* PA7: ETH_RMII_CRS_DV */ - gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7); - gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_7); - - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_1); - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_2); - gpio_af_set(GPIOA, GPIO_AF_11, GPIO_PIN_7); - - /* PB11: ETH_RMII_TX_EN */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_11); - - /* PB12: ETH_RMII_TXD0 */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_12); - - /* PB13: ETH_RMII_TXD1 */ - gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13); - gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_13); - - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_11); - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_12); - gpio_af_set(GPIOB, GPIO_AF_11, GPIO_PIN_13); - - /* PC1: ETH_MDC */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_1); - - /* PC4: ETH_RMII_RXD0 */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_4); - - /* PC5: ETH_RMII_RXD1 */ - gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5); - gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ, GPIO_PIN_5); - - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_1); - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_4); - gpio_af_set(GPIOC, GPIO_AF_11, GPIO_PIN_5); - - /* enable the ETHERNET global interrupt */ - nvic_irq_enable(ENET_IRQn, 0x7, 0); - - /* enable ETHERNET clock */ - rcu_periph_clock_enable(RCU_ENET); - rcu_periph_clock_enable(RCU_ENETTX); - rcu_periph_clock_enable(RCU_ENETRX); -} diff --git a/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.cpp b/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.cpp deleted file mode 100644 index f08c041..0000000 --- a/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 GigaDevice Semiconductor Inc. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "mbed_shared_queues.h" -#include "netsocket/nsapi_types.h" - -#include "gd32xx_emac.h" - -using namespace std::chrono; - -/* \brief Flags for worker thread */ -#define _ENET_FLAG_RX (1) - -/** \brief Driver thread priority */ -#define _THREAD_STACKSIZE (512) -#define _THREAD_PRIORITY (osPriorityHigh) - -#define _PHY_TASK_PERIOD (200ms) - -#define _ENET_HW_ADDR_SIZE (6) -#define _ENET_MTU_SIZE (1500) -#define _ENET_IF_NAME "gd" - -#define _ENET_BOARD_PHY_ADDRESS (0x01) -#define _ENET_HARDWARE_CHECKSUM (0) - -#define _GD_MAC_ADDR0 0x02 -#define _GD_MAC_ADDR1 0xaa -#define _GD_MAC_ADDR2 0xbb -#define _GD32_ID_ADDR 0x1FFFF7E8 -/* ENET RxDMA/TxDMA descriptor */ -extern enet_descriptors_struct rxdesc_tab[ENET_RXBUF_NUM], txdesc_tab[ENET_TXBUF_NUM]; -/* ENET receive buffer */ -extern uint8_t rx_buff[ENET_RXBUF_NUM][ENET_RXBUF_SIZE]; -/* ENET transmit buffer */ -extern uint8_t tx_buff[ENET_TXBUF_NUM][ENET_TXBUF_SIZE]; -/*global transmit and receive descriptors pointers */ -extern enet_descriptors_struct *dma_current_txdesc; -extern enet_descriptors_struct *dma_current_rxdesc; - -#ifdef __cplusplus -extern "C" { -#endif - -void ENET_IRQHandler(void); -void enet_bsp_init(void); -#ifdef __cplusplus -} -#endif - -/** - * Ethernet IRQ Handler - * - */ -void ENET_IRQHandler(void) -{ - /* frame received */ - if (SET == enet_interrupt_flag_get(ENET_DMA_INT_FLAG_RS)) { - /* clear the enet DMA Rx interrupt pending bits */ - enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_RS_CLR); - enet_interrupt_flag_clear(ENET_DMA_INT_FLAG_NI_CLR); - /* Ethernet Rx Transfer completed callback */ - GD32_EMAC &emac = GD32_EMAC::get_instance(); - if (emac.rx_thread) { - osThreadFlagsSet(emac.rx_thread, _ENET_FLAG_RX); - } - } -} - -GD32_EMAC::GD32_EMAC() - : rx_thread(0), - phy_status(0) -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} - -/** \brief Low level init of the MAC and PHY. - * - */ -bool GD32_EMAC::low_level_init() -{ - /* Init ETH */ - uint8_t macaddr[6]; - uint32_t i; - -#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) - MACAddr[0] = MBED_MAC_ADDR_0; - MACAddr[1] = MBED_MAC_ADDR_1; - MACAddr[2] = MBED_MAC_ADDR_2; - MACAddr[3] = MBED_MAC_ADDR_3; - MACAddr[4] = MBED_MAC_ADDR_4; - MACAddr[5] = MBED_MAC_ADDR_5; -#else - mbed_mac_address((char *)macaddr); -#endif - - enet_bsp_init(); - /* reset ethernet on AHB bus */ - enet_deinit(); - - if (ERROR == enet_software_reset()) { - while (1); - } - -#if (1 == _ENET_HARDWARE_CHECKSUM) - if (ERROR == enet_init(ENET_AUTO_NEGOTIATION, ENET_AUTOCHECKSUM_DROP_FAILFRAMES, ENET_BROADCAST_FRAMES_PASS)) { - while (1); - } -#else - if (ERROR == enet_init(ENET_AUTO_NEGOTIATION, ENET_NO_AUTOCHECKSUM, ENET_BROADCAST_FRAMES_PASS)) { - while (1); - } -#endif - /* initialize MAC address in ethernet MAC */ - enet_mac_address_set(ENET_MAC_ADDRESS0, macaddr); - - enet_interrupt_enable(ENET_DMA_INT_NIE); - enet_interrupt_enable(ENET_DMA_INT_RIE); - - /* Initialize Tx Descriptors list: Chain Mode */ - enet_descriptors_chain_init(ENET_DMA_TX); - -#if (1 == _ENET_HARDWARE_CHECKSUM) - /* enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ - for (i = 0; i < ENET_TXBUF_NUM; i++) { - enet_transmit_checksum_config(&txdesc_tab[i], ENET_CHECKSUM_TCPUDPICMP_FULL); - } -#endif - - /* Initialize Rx Descriptors list: Chain Mode */ - enet_descriptors_chain_init(ENET_DMA_RX); - - /* enable ethernet Rx interrrupt */ - for (i = 0; i < ENET_RXBUF_NUM; i++) { - enet_rx_desc_immediate_receive_complete_interrupt(&rxdesc_tab[i]); - } - - /* enable MAC and DMA transmission and reception */ - enet_enable(); - - return true; -} - -/** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ -bool GD32_EMAC::link_out(emac_mem_buf_t *buf) -{ - emac_mem_buf_t *q; - uint8_t *buffer; - uint16_t framelength = 0; - - /* Get exclusive access */ - TXLockMutex.lock(); - - while ((uint32_t)RESET != (dma_current_txdesc->status & ENET_TDES0_DAV)) {} - - /* copy frame from pbufs to driver buffers */ - buffer = reinterpret_cast(enet_desc_information_get(dma_current_txdesc, TXDESC_BUFFER_1_ADDR)); - - for (q = buf; q != NULL; q = memory_manager->get_next(q)) { - memcpy(static_cast(&buffer[framelength]), static_cast(memory_manager->get_ptr(q)), memory_manager->get_len(q)); - framelength = framelength + memory_manager->get_len(q); - } - - /* Prepare transmit descriptors to give to DMA */ - if (SUCCESS != ENET_NOCOPY_FRAME_TRANSMIT(framelength)) { - while (1); - } - - memory_manager->free(buf); - /* Restore access */ - TXLockMutex.unlock(); - - return true; -} - -/** \brief Attempt to read a packet from the EMAC interface. - * - */ -emac_mem_buf_t *GD32_EMAC::low_level_input(void) -{ - emac_mem_buf_t *p = NULL, *q; - uint32_t l = 0; - uint16_t len; - uint8_t *buffer; - - /* obtain the size of the packet and put it into the "len" variable. */ - len = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH); - buffer = reinterpret_cast(enet_desc_information_get(dma_current_rxdesc, RXDESC_BUFFER_1_ADDR)); - - if (len > 0) { - /* Allocate a memory buffer chain from buffer pool */ - p = memory_manager->alloc_pool(len, 0); - } else { - return p; - } - - if (p != NULL) { - for (q = p; q != NULL; q = memory_manager->get_next(q)) { - memcpy(static_cast(memory_manager->get_ptr(q)), static_cast(&buffer[l]), memory_manager->get_len(q)); - l = l + memory_manager->get_len(q); - } - } - ENET_NOCOPY_FRAME_RECEIVE(); - - return p; -} - - -/** \brief Attempt to read a packet from the EMAC interface. - * - */ -void GD32_EMAC::packet_rx() -{ - /* move received packet into a new buf */ - while (1) { - emac_mem_buf_t *p = NULL; - p = low_level_input(); - - if (p) { - emac_link_input_cb(p); - } else { - break; - } - } -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void GD32_EMAC::thread_function(void *pvParameters) -{ - static struct GD32_EMAC *gd32_enet = static_cast(pvParameters); - - while (1) { - uint32_t flags = osThreadFlagsWait(_ENET_FLAG_RX, osFlagsWaitAny, osWaitForever); - - if (flags & _ENET_FLAG_RX) { - gd32_enet->packet_rx(); - } - } -} - -/** - * This task checks phy link status and updates net status - */ -void GD32_EMAC::phy_task() -{ - uint16_t regval; - - enet_phy_write_read(ENET_PHY_READ, _ENET_BOARD_PHY_ADDRESS, PHY_REG_BSR, ®val); - if (emac_link_state_cb) { - regval &= PHY_LINKED_STATUS; - - if (phy_status != regval) { - if (regval == PHY_LINKED_STATUS) { - emac_link_state_cb(true);; - } else { - emac_link_state_cb(false); - } - } - } - - phy_status = regval; -} - -void GD32_EMAC::eth_arch_enable_interrupts(void) -{ - nvic_irq_enable(ENET_IRQn, 7, 0); -} - -void GD32_EMAC::eth_arch_disable_interrupts(void) -{ - nvic_irq_disable(ENET_IRQn); -} - -/** This returns a unique 6-byte MAC address, based on the device UID -* This function overrides hal/common/mbed_interface.c function -* @param mac A 6-byte array to write the MAC address -*/ -void mbed_mac_address(char *mac) -{ - uint32_t unique_id; - - unique_id = *(uint32_t *)_GD32_ID_ADDR; - mac[0] = _GD_MAC_ADDR0; - mac[1] = _GD_MAC_ADDR1; - mac[2] = _GD_MAC_ADDR2; - mac[3] = (unique_id & 0x00ff0000) >> 16; - mac[4] = (unique_id & 0x0000ff00) >> 8; - mac[5] = (unique_id & 0x000000ff); -} - -/** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ -bool GD32_EMAC::power_up() -{ - /* Initialize the hardware */ - if (true != low_level_init()) { - return false; - } - - /* Worker thread */ - rx_thread = create_new_thread("gd32_emac_thread", &GD32_EMAC::thread_function, this, _THREAD_STACKSIZE, _THREAD_PRIORITY, &rx_thread_cb); - - phy_task_handle = mbed::mbed_event_queue()->call_every(_PHY_TASK_PERIOD, mbed::callback(this, &GD32_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - eth_arch_enable_interrupts(); - - return true; -} - -/** - * Return maximum transmission unit - * - * @return MTU in bytes - */ -uint32_t GD32_EMAC::get_mtu_size() const -{ - return _ENET_MTU_SIZE; -} - -/** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ -uint32_t GD32_EMAC::get_align_preference() const -{ - return 0; -} - -/** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ -void GD32_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, _ENET_IF_NAME, (size < sizeof(_ENET_IF_NAME)) ? size : sizeof(_ENET_IF_NAME)); -} - -/** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ -uint8_t GD32_EMAC::get_hwaddr_size() const -{ - return _ENET_HW_ADDR_SIZE; -} - -/** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ -bool GD32_EMAC::get_hwaddr(uint8_t *addr) const -{ - mbed_mac_address((char *)addr); - return true; -} - -/** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ -void GD32_EMAC::set_hwaddr(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -/** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ -void GD32_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -/** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ -void GD32_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -/** Add device to a multicast group - * - * @param address A multicast group hardware address - */ -void GD32_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -/** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ -void GD32_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -/** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ -void GD32_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -/** - * Deinitializes the HW - * - */ -void GD32_EMAC::power_down() -{ - /* No-op at this stage */ -} - -/** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ -void GD32_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -GD32_EMAC &GD32_EMAC::get_instance() -{ - static GD32_EMAC emac; - return emac; -} - -/* Weak so a module can override */ -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return GD32_EMAC::get_instance(); -} diff --git a/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.h b/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.h deleted file mode 100644 index 0284c99..0000000 --- a/features/netsocket/emac-drivers/TARGET_GD_EMAC/gd32xx_emac.h +++ /dev/null @@ -1,175 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 GigaDevice Semiconductor Inc. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef GD32_EMAC_H_ -#define GD32_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Mutex.h" - -class GD32_EMAC : public EMAC { -public: - GD32_EMAC(); - - static GD32_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - /* Called from driver functions */ - osThreadId_t rx_thread; /**< Processing rx thread */ - -private: - bool low_level_init(); - void packet_rx(); - emac_mem_buf_t *low_level_input(void); - static void thread_function(void *pvParameters); - void phy_task(); - void eth_arch_enable_interrupts(); - void eth_arch_disable_interrupts(); - - mbed_rtos_storage_thread_t rx_thread_cb; - - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - - uint32_t phy_status; - int phy_task_handle; /**< Handle for phy task event */ -}; - -#endif /* GD32_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c deleted file mode 100644 index dc8dfea..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Description: M480 MAC driver source file - */ -#include -#include "m480_eth.h" -#include "mbed_toolchain.h" -//#define NU_TRACE -#include "numaker_eth_hal.h" - -#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) -#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) -#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) -#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0) -#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) -#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0) - -#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel)) -#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel)) - -MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; -MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; - -struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; - -__attribute__((section("EMAC_RAM"))) -MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; -__attribute__((section("EMAC_RAM"))) -MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; - -eth_callback_t nu_eth_txrx_cb = NULL; -void *nu_userData = NULL; - -extern void ack_emac_rx_isr(void); - -static bool isPhyReset = false; -static uint16_t phyLPAval = 0; - -// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns -// Assume we want to set each tick to 100ns. -// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 -// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz -// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 - - - -static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) -{ - - EMAC->MIIMDAT = val; - EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; - - while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); - -} - - -static uint16_t mdio_read(uint8_t addr, uint8_t reg) -{ - EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; - while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); - - return (EMAC->MIIMDAT); -} - -static int reset_phy(void) -{ - - uint16_t reg; - uint32_t delayCnt; - - - mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); - - delayCnt = 2000; - while (delayCnt > 0) { - delayCnt--; - if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) { - break; - } - - } - - if (delayCnt == 0) { - NU_DEBUGF(("Reset phy failed\n")); - return (-1); - } - - mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | - ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL); - - reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); - mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); - - delayCnt = 200000; - while (delayCnt > 0) { - delayCnt--; - if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) - == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) { - break; - } - } - - if (delayCnt == 0) { - NU_DEBUGF(("AN failed. Set to 100 FULL\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - return (-1); - } else { - reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); - phyLPAval = reg; - - if (reg & ADVERTISE_100FULL) { - NU_DEBUGF(("100 full\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } else if (reg & ADVERTISE_100HALF) { - NU_DEBUGF(("100 half\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; - } else if (reg & ADVERTISE_10FULL) { - NU_DEBUGF(("10 full\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; - } else { - NU_DEBUGF(("10 half\n")); - EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } - } - printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)); - printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)); - - return (0); -} - - -static void init_tx_desc(void) -{ - uint32_t i; - - - cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; - - for (i = 0; i < TX_DESCRIPTOR_NUM; i++) { - tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; - tx_desc[i].buf = &tx_buf[i][0]; - tx_desc[i].status2 = 0; - tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; - - } - EMAC->TXDSA = (unsigned int)&tx_desc[0]; - return; -} - -static void init_rx_desc(void) -{ - uint32_t i; - - - cur_rx_desc_ptr = &rx_desc[0]; - - for (i = 0; i < RX_DESCRIPTOR_NUM; i++) { - rx_desc[i].status1 = OWNERSHIP_EMAC; - rx_desc[i].buf = &rx_buf[i][0]; - rx_desc[i].status2 = 0; - rx_desc[i].next = &rx_desc[(i + 1) % RX_DESCRIPTOR_NUM]; - } - EMAC->RXDSA = (unsigned int)&rx_desc[0]; - return; -} - -void numaker_set_mac_addr(uint8_t *addr) -{ - - EMAC->CAM0M = (addr[0] << 24) | - (addr[1] << 16) | - (addr[2] << 8) | - addr[3]; - - EMAC->CAM0L = (addr[4] << 24) | - (addr[5] << 16); - - -} - -static void __eth_clk_pin_init() -{ - /* Unlock protected registers */ - SYS_UnlockReg(); - - /* Enable IP clock */ - CLK_EnableModuleClock(EMAC_MODULE); - - // Configure MDC clock rate to HCLK / (127 + 1) = 1.25 MHz if system is running at 160 MH - CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); - - /* Update System Core Clock */ - SystemCoreClockUpdate(); - - /*---------------------------------------------------------------------------------------------------------*/ - /* Init I/O Multi-function */ - /*---------------------------------------------------------------------------------------------------------*/ - // Configure RMII pins - SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA6MFP_Msk | SYS_GPA_MFPL_PA7MFP_Msk); - SYS->GPA_MFPL |= SYS_GPA_MFPL_PA6MFP_EMAC_RMII_RXERR | SYS_GPA_MFPL_PA7MFP_EMAC_RMII_CRSDV; - SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); - SYS->GPC_MFPL |= SYS_GPC_MFPL_PC6MFP_EMAC_RMII_RXD1 | SYS_GPC_MFPL_PC7MFP_EMAC_RMII_RXD0; - SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; - SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_RMII_REFCLK; - SYS->GPE_MFPH &= ~(SYS_GPE_MFPH_PE8MFP_Msk | SYS_GPE_MFPH_PE9MFP_Msk | SYS_GPE_MFPH_PE10MFP_Msk | - SYS_GPE_MFPH_PE11MFP_Msk | SYS_GPE_MFPH_PE12MFP_Msk); - SYS->GPE_MFPH |= SYS_GPE_MFPH_PE8MFP_EMAC_RMII_MDC | - SYS_GPE_MFPH_PE9MFP_EMAC_RMII_MDIO | - SYS_GPE_MFPH_PE10MFP_EMAC_RMII_TXD0 | - SYS_GPE_MFPH_PE11MFP_EMAC_RMII_TXD1 | - SYS_GPE_MFPH_PE12MFP_EMAC_RMII_TXEN; - - // Enable high slew rate on all RMII TX output pins - PE->SLEWCTL = (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN10_Pos) | - (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN11_Pos) | - (GPIO_SLEWCTL_HIGH << GPIO_SLEWCTL_HSREN12_Pos); - - - /* Lock protected registers */ - SYS_LockReg(); - - -} - -void numaker_eth_init(uint8_t *mac_addr) -{ - - // init CLK & pins - __eth_clk_pin_init(); - - // Reset MAC - EMAC->CTL = EMAC_CTL_RST_Msk; - while (EMAC->CTL & EMAC_CTL_RST_Msk) {} - - init_tx_desc(); - init_rx_desc(); - - numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... - - - /* Configure the MAC interrupt enable register. */ - EMAC->INTEN = EMAC_INTEN_RXIEN_Msk | - EMAC_INTEN_TXIEN_Msk | - EMAC_INTEN_RXGDIEN_Msk | - EMAC_INTEN_TXCPIEN_Msk | - EMAC_INTEN_RXBEIEN_Msk | - EMAC_INTEN_TXBEIEN_Msk | - EMAC_INTEN_RDUIEN_Msk | - EMAC_INTEN_TSALMIEN_Msk | - EMAC_INTEN_WOLIEN_Msk; - - /* Configure the MAC control register. */ - EMAC->CTL = EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RMIIEN_Msk; - - /* Accept packets for us and all broadcast and multicast packets */ - EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | - EMAC_CAMCTL_AMP_Msk | - EMAC_CAMCTL_ABP_Msk; - EMAC->CAMEN = 1; // Enable CAM entry 0 - /* Limit the max receive frame length to 1514 + 4 */ - EMAC->MRFL = NU_ETH_MAX_FLEN; - - /* Set RX FIFO threshold as 8 words */ - EMAC->FIFOCTL = 0x00200100; - - if (isPhyReset != true) { - if (!reset_phy()) { - isPhyReset = true; - } - } else { - if (phyLPAval & ADVERTISE_100FULL) { - NU_DEBUGF(("100 full\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } else if (phyLPAval & ADVERTISE_100HALF) { - NU_DEBUGF(("100 half\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; - } else if (phyLPAval & ADVERTISE_10FULL) { - NU_DEBUGF(("10 full\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; - } else { - NU_DEBUGF(("10 half\n")); - EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } - } - - EMAC_ENABLE_RX(); - EMAC_ENABLE_TX(); - -} - - - -void ETH_halt(void) -{ - - EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); -} - -unsigned int m_status; - -void EMAC_RX_IRQHandler(void) -{ - m_status = EMAC->INTSTS & 0xFFFF; - EMAC->INTSTS = m_status; - if (m_status & EMAC_INTSTS_RXBEIF_Msk) { - // Shouldn't goes here, unless descriptor corrupted - mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('B', nu_userData); - } - return; - } - EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('R', nu_userData); - } -} - - -void numaker_eth_trigger_rx(void) -{ - EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); - ETH_TRIGGER_RX(); -} - -int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) -{ - unsigned int cur_entry, status; - - cur_entry = EMAC->CRXDSA; - if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures - return -1; - } - status = cur_rx_desc_ptr->status1; - - if (status & OWNERSHIP_EMAC) { - return -1; - } - - if (status & RXFD_RXGD) { - *buf = cur_rx_desc_ptr->buf; - *len = status & 0xFFFF; - // length of payload should be <= 1514 - if (*len > (NU_ETH_MAX_FLEN - 4)) { - NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); - *len = 0; // Skip this unexpected long packet - } - if (*len == (NU_ETH_MAX_FLEN - 4)) { - NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); - } - } - return 0; -} - -void numaker_eth_rx_next(void) -{ - cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; - cur_rx_desc_ptr = cur_rx_desc_ptr->next; -} - -void EMAC_TX_IRQHandler(void) -{ - unsigned int cur_entry, status; - - status = EMAC->INTSTS & 0xFFFF0000; - EMAC->INTSTS = status; - if (status & EMAC_INTSTS_TXBEIF_Msk) { - // Shouldn't goes here, unless descriptor corrupted - mbed_error_printf("### TX Bus error [0x%x]\r\n", status); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('B', nu_userData); - } - return; - } - - cur_entry = EMAC->CTXDSA; - - while (cur_entry != (uint32_t)fin_tx_desc_ptr) { - - fin_tx_desc_ptr = fin_tx_desc_ptr->next; - } - - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('T', nu_userData); - } -} - -uint8_t *numaker_eth_get_tx_buf(void) -{ - if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) { - return (NULL); - } else { - return (cur_tx_desc_ptr->buf); - } -} - -void numaker_eth_trigger_tx(uint16_t length, void *p) -{ - struct eth_descriptor volatile *desc; - cur_tx_desc_ptr->status2 = (unsigned int)length; - desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr - cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; - cur_tx_desc_ptr = desc; - - ETH_TRIGGER_TX(); - -} - -int numaker_eth_link_ok(void) -{ - /* first, a dummy read to latch */ - mdio_read(CONFIG_PHY_ADDR, MII_BMSR); - if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) { - return 1; - } - return 0; -} - -void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) -{ - nu_eth_txrx_cb = eth_cb; - nu_userData = userData; -} - -// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address -void mbed_mac_address(char *mac) -{ - uint32_t uID1; - // Fetch word 0 - uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 - // Fetch word 1 - // we only want bottom 16 bits of word1 (MAC bits 32-47) - // and bit 9 forced to 1, bit 8 forced to 0 - // Locally administered MAC, reduced conflicts - // http://en.wikipedia.org/wiki/MAC_address - uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 - - if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash - // with a semi-unique MAC address from the UUID - /* Enable FMC ISP function */ - SYS_UnlockReg(); - FMC_Open(); - // = FMC_ReadUID(0); - uID1 = FMC_ReadUID(1); - word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; - word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF); - /* Disable FMC ISP function */ - FMC_Close(); - /* Lock protected registers */ - SYS_LockReg(); - } - - word1 |= 0x00000200; - word1 &= 0x0000FEFF; - - mac[0] = (word1 & 0x0000ff00) >> 8; - mac[1] = (word1 & 0x000000ff); - mac[2] = (word0 & 0xff000000) >> 24; - mac[3] = (word0 & 0x00ff0000) >> 16; - mac[4] = (word0 & 0x0000ff00) >> 8; - mac[5] = (word0 & 0x000000ff); - - NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); -} - -void numaker_eth_enable_interrupts(void) -{ - EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | - EMAC_INTEN_TXIEN_Msk ; - NVIC_EnableIRQ(EMAC_RX_IRQn); - NVIC_EnableIRQ(EMAC_TX_IRQn); -} - -void numaker_eth_disable_interrupts(void) -{ - NVIC_DisableIRQ(EMAC_RX_IRQn); - NVIC_DisableIRQ(EMAC_TX_IRQn); -} diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h deleted file mode 100644 index 9a1be26..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_M480/m480_eth.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Description: M480 EMAC driver header file - */ - -#include "numaker_emac_config.h" -#include "M480.h" -#ifndef _M480_ETH_ -#define _M480_ETH_ - -/* Generic MII registers. */ - -#define MII_BMCR 0x00 /* Basic mode control register */ -#define MII_BMSR 0x01 /* Basic mode status register */ -#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define MII_LPA 0x05 /* Link partner ability reg */ -#define MII_EXPANSION 0x06 /* Expansion register */ -#define MII_DCOUNTER 0x12 /* Disconnect counter */ -#define MII_FCSCOUNTER 0x13 /* False carrier counter */ -#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ -#define MII_RERRCOUNTER 0x15 /* Receive error counter */ -#define MII_SREVISION 0x16 /* Silicon revision */ -#define MII_RESV1 0x17 /* Reserved... */ -#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ -#define MII_PHYADDR 0x19 /* PHY address */ -#define MII_RESV2 0x1a /* Reserved... */ -#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ -#define MII_NCONFIG 0x1c /* Network interface config */ - -/* Basic mode control register. */ -#define BMCR_RESV 0x007f /* Unused... */ -#define BMCR_CTST 0x0080 /* Collision test */ -#define BMCR_FULLDPLX 0x0100 /* Full duplex */ -#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ -#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ -#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ -#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ -#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ -#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ -#define BMCR_RESET 0x8000 /* Reset the DP83840 */ - -/* Basic mode status register. */ -#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ -#define BMSR_JCD 0x0002 /* Jabber detected */ -#define BMSR_LSTATUS 0x0004 /* Link status */ -#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ -#define BMSR_RFAULT 0x0010 /* Remote fault detected */ -#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ -#define BMSR_RESV 0x07c0 /* Unused... */ -#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ -#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ -#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ -#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ -#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ - -/* Advertisement control register. */ -#define ADVERTISE_SLCT 0x001f /* Selector bits */ -#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ -#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ -#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ -#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ -#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ -#define ADVERTISE_RESV 0x1c00 /* Unused... */ -#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ -#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ -#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ - -#define RX_DESCRIPTOR_NUM NU_RX_RING_LEN//4 //2 // 4: Max Number of Rx Frame Descriptors -#define TX_DESCRIPTOR_NUM NU_TX_RING_LEN//4 //2 // 4: Max number of Tx Frame Descriptors - -#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment - -#define CONFIG_PHY_ADDR 1 - - -// Frame Descriptor's Owner bit -#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC -//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU - - - -// Rx Frame Descriptor Status -#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received -#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available - - -// Tx Frame Descriptor's Control bits -#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable -#define TXFD_INTEN 0x04 // Interrupt Enable -#define TXFD_CRCAPP 0x02 // Append CRC -#define TXFD_PADEN 0x01 // Padding Enable - -// Tx Frame Descriptor Status -#define TXFD_TXCP 0x00080000 // Transmission Completion -#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available - -// Tx/Rx buffer descriptor structure -struct eth_descriptor; -struct eth_descriptor { - uint32_t status1; - uint8_t *buf; - uint32_t status2; - struct eth_descriptor *next; -#ifdef TIME_STAMPING - uint32_t backup1; - uint32_t backup2; - uint32_t reserved1; - uint32_t reserved2; -#endif -}; - -#ifdef TIME_STAMPING - -#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) -#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) -s32_t ETH_settime(u32_t sec, u32_t nsec); -s32_t ETH_gettime(u32_t *sec, u32_t *nsec); -s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); -s32_t ETH_adjtimex(int ppm); -void ETH_setinc(void); - -#endif - -#endif /* _M480_ETH_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c deleted file mode 100644 index e0f77b7..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Description: NUC472 MAC driver source file - */ -#include -#include "nuc472_eth.h" -#include "mbed_toolchain.h" -//#define NU_TRACE -#include "numaker_eth_hal.h" - -#define ETH_TRIGGER_RX() do{EMAC->RXST = 0;}while(0) -#define ETH_TRIGGER_TX() do{EMAC->TXST = 0;}while(0) -#define ETH_ENABLE_TX() do{EMAC->CTL |= EMAC_CTL_TXON;}while(0) -#define ETH_ENABLE_RX() do{EMAC->CTL |= EMAC_CTL_RXON_Msk;}while(0) -#define ETH_DISABLE_TX() do{EMAC->CTL &= ~EMAC_CTL_TXON;}while(0) -#define ETH_DISABLE_RX() do{EMAC->CTL &= ~EMAC_CTL_RXON_Msk;}while(0) - -#define EMAC_ENABLE_INT(emac, u32eIntSel) ((emac)->INTEN |= (u32eIntSel)) -#define EMAC_DISABLE_INT(emac, u32eIntSel) ((emac)->INTEN &= ~ (u32eIntSel)) - -MBED_ALIGN(4) struct eth_descriptor rx_desc[RX_DESCRIPTOR_NUM]; -MBED_ALIGN(4) struct eth_descriptor tx_desc[TX_DESCRIPTOR_NUM]; - -struct eth_descriptor volatile *cur_tx_desc_ptr, *cur_rx_desc_ptr, *fin_tx_desc_ptr; - -__attribute__((section("EMAC_RAM"))) -MBED_ALIGN(4) uint8_t rx_buf[RX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; -__attribute__((section("EMAC_RAM"))) -MBED_ALIGN(4) uint8_t tx_buf[TX_DESCRIPTOR_NUM][PACKET_BUFFER_SIZE]; - -eth_callback_t nu_eth_txrx_cb = NULL; -void *nu_userData = NULL; - -extern void ack_emac_rx_isr(void); -static bool isPhyReset = false; -static uint16_t phyLPAval = 0; - -// PTP source clock is 84MHz (Real chip using PLL). Each tick is 11.90ns -// Assume we want to set each tick to 100ns. -// Increase register = (100 * 2^31) / (10^9) = 214.71 =~ 215 = 0xD7 -// Addend register = 2^32 * tick_freq / (84MHz), where tick_freq = (2^31 / 215) MHz -// From above equation, addend register = 2^63 / (84M * 215) ~= 510707200 = 0x1E70C600 - - - -static void mdio_write(uint8_t addr, uint8_t reg, uint16_t val) -{ - - EMAC->MIIMDAT = val; - EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_WRITE_Msk | EMAC_MIIMCTL_MDCON_Msk; - - while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); - -} - - -static uint16_t mdio_read(uint8_t addr, uint8_t reg) -{ - EMAC->MIIMCTL = (addr << EMAC_MIIMCTL_PHYADDR_Pos) | reg | EMAC_MIIMCTL_BUSY_Msk | EMAC_MIIMCTL_MDCON_Msk; - while (EMAC->MIIMCTL & EMAC_MIIMCTL_BUSY_Msk); - - return (EMAC->MIIMDAT); -} - -static int reset_phy(void) -{ - - uint16_t reg; - uint32_t delayCnt; - - - mdio_write(CONFIG_PHY_ADDR, MII_BMCR, BMCR_RESET); - - delayCnt = 2000; - while (delayCnt > 0) { - delayCnt--; - if ((mdio_read(CONFIG_PHY_ADDR, MII_BMCR) & BMCR_RESET) == 0) { - break; - } - - } - - if (delayCnt == 0) { - NU_DEBUGF(("Reset phy failed\n")); - return (-1); - } - - mdio_write(CONFIG_PHY_ADDR, MII_ADVERTISE, ADVERTISE_CSMA | - ADVERTISE_10HALF | - ADVERTISE_10FULL | - ADVERTISE_100HALF | - ADVERTISE_100FULL); - - reg = mdio_read(CONFIG_PHY_ADDR, MII_BMCR); - mdio_write(CONFIG_PHY_ADDR, MII_BMCR, reg | BMCR_ANRESTART); - - delayCnt = 200000; - while (delayCnt > 0) { - delayCnt--; - if ((mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) - == (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) { - break; - } - } - - if (delayCnt == 0) { - NU_DEBUGF(("AN failed. Set to 100 FULL\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - return (-1); - } else { - reg = mdio_read(CONFIG_PHY_ADDR, MII_LPA); - phyLPAval = reg; - - if (reg & ADVERTISE_100FULL) { - NU_DEBUGF(("100 full\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } else if (reg & ADVERTISE_100HALF) { - NU_DEBUGF(("100 half\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; - } else if (reg & ADVERTISE_10FULL) { - NU_DEBUGF(("10 full\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; - } else { - NU_DEBUGF(("10 half\n")); - EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } - } - printf("PHY ID 1:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID1)); - printf("PHY ID 2:0x%x\r\n", mdio_read(CONFIG_PHY_ADDR, MII_PHYSID2)); - - return (0); -} - - -static void init_tx_desc(void) -{ - uint32_t i; - - - cur_tx_desc_ptr = fin_tx_desc_ptr = &tx_desc[0]; - - for (i = 0; i < TX_DESCRIPTOR_NUM; i++) { - tx_desc[i].status1 = TXFD_PADEN | TXFD_CRCAPP | TXFD_INTEN; - tx_desc[i].buf = &tx_buf[i][0]; - tx_desc[i].status2 = 0; - tx_desc[i].next = &tx_desc[(i + 1) % TX_DESCRIPTOR_NUM]; - - } - EMAC->TXDSA = (unsigned int)&tx_desc[0]; - return; -} - -static void init_rx_desc(void) -{ - uint32_t i; - - - cur_rx_desc_ptr = &rx_desc[0]; - - for (i = 0; i < RX_DESCRIPTOR_NUM; i++) { - rx_desc[i].status1 = OWNERSHIP_EMAC; - rx_desc[i].buf = &rx_buf[i][0]; - rx_desc[i].status2 = 0; - rx_desc[i].next = &rx_desc[(i + 1) % (RX_DESCRIPTOR_NUM)]; - } - EMAC->RXDSA = (unsigned int)&rx_desc[0]; - return; -} - -void numaker_set_mac_addr(uint8_t *addr) -{ - - EMAC->CAM0M = (addr[0] << 24) | - (addr[1] << 16) | - (addr[2] << 8) | - addr[3]; - - EMAC->CAM0L = (addr[4] << 24) | - (addr[5] << 16); - - EMAC->CAMCTL = EMAC_CAMCTL_CMPEN_Msk | EMAC_CAMCTL_AMP_Msk | EMAC_CAMCTL_ABP_Msk; - EMAC->CAMEN = 1; // Enable CAM entry 0 - -} - -static void __eth_clk_pin_init() -{ - /* Unlock protected registers */ - SYS_UnlockReg(); - /* Enable IP clock */ - CLK_EnableModuleClock(EMAC_MODULE); - // Configure MDC clock rate to HCLK / (127 + 1) = 656 kHz if system is running at 84 MHz - CLK_SetModuleClock(EMAC_MODULE, 0, CLK_CLKDIV3_EMAC(127)); - /* Update System Core Clock */ - SystemCoreClockUpdate(); - /*---------------------------------------------------------------------------------------------------------*/ - /* Init I/O Multi-function */ - /*---------------------------------------------------------------------------------------------------------*/ - // Configure RMII pins - SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC0MFP_Msk | SYS_GPC_MFPL_PC1MFP_Msk | - SYS_GPC_MFPL_PC2MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk | - SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC6MFP_Msk | SYS_GPC_MFPL_PC7MFP_Msk); - SYS->GPC_MFPL |= SYS_GPC_MFPL_PC0MFP_EMAC_REFCLK | - SYS_GPC_MFPL_PC1MFP_EMAC_MII_RXERR | - SYS_GPC_MFPL_PC2MFP_EMAC_MII_RXDV | - SYS_GPC_MFPL_PC3MFP_EMAC_MII_RXD1 | - SYS_GPC_MFPL_PC4MFP_EMAC_MII_RXD0 | - SYS_GPC_MFPL_PC6MFP_EMAC_MII_TXD0 | - SYS_GPC_MFPL_PC7MFP_EMAC_MII_TXD1; - - SYS->GPC_MFPH &= ~SYS_GPC_MFPH_PC8MFP_Msk; - SYS->GPC_MFPH |= SYS_GPC_MFPH_PC8MFP_EMAC_MII_TXEN; - // Enable high slew rate on all RMII pins - PC->SLEWCTL |= 0x1DF; - - // Configure MDC, MDIO at PB14 & PB15 - SYS->GPB_MFPH &= ~(SYS_GPB_MFPH_PB14MFP_Msk | SYS_GPB_MFPH_PB15MFP_Msk); - SYS->GPB_MFPH |= SYS_GPB_MFPH_PB14MFP_EMAC_MII_MDC | SYS_GPB_MFPH_PB15MFP_EMAC_MII_MDIO; - - /* Lock protected registers */ - SYS_LockReg(); -} - -void numaker_eth_init(uint8_t *mac_addr) -{ - // init CLK & pins - __eth_clk_pin_init(); - - // Reset MAC - EMAC->CTL = EMAC_CTL_RST_Msk; - while (EMAC->CTL & EMAC_CTL_RST_Msk) {} - - init_tx_desc(); - init_rx_desc(); - - numaker_set_mac_addr(mac_addr); // need to reconfigure hardware address 'cos we just RESET emc... - - - EMAC->CTL |= EMAC_CTL_STRIPCRC_Msk | EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk | EMAC_CTL_RMIIEN_Msk | EMAC_CTL_RMIIRXCTL_Msk; - EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | - EMAC_INTEN_RXGDIEN_Msk | - EMAC_INTEN_RDUIEN_Msk | - EMAC_INTEN_RXBEIEN_Msk | - EMAC_INTEN_TXIEN_Msk | - EMAC_INTEN_TXABTIEN_Msk | - EMAC_INTEN_TXCPIEN_Msk | - EMAC_INTEN_TXBEIEN_Msk; - /* Limit the max receive frame length to 1514 + 4 */ - EMAC->MRFL = NU_ETH_MAX_FLEN; - - /* Set RX FIFO threshold as 8 words */ - - if (isPhyReset != true) { - if (!reset_phy()) { - isPhyReset = true; - } - } else { - if (phyLPAval & ADVERTISE_100FULL) { - NU_DEBUGF(("100 full\n")); - EMAC->CTL |= (EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } else if (phyLPAval & ADVERTISE_100HALF) { - NU_DEBUGF(("100 half\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_FUDUP_Msk) | EMAC_CTL_OPMODE_Msk; - } else if (phyLPAval & ADVERTISE_10FULL) { - NU_DEBUGF(("10 full\n")); - EMAC->CTL = (EMAC->CTL & ~EMAC_CTL_OPMODE_Msk) | EMAC_CTL_FUDUP_Msk; - } else { - NU_DEBUGF(("10 half\n")); - EMAC->CTL &= ~(EMAC_CTL_OPMODE_Msk | EMAC_CTL_FUDUP_Msk); - } - } - - EMAC_ENABLE_RX(); - EMAC_ENABLE_TX(); - -} - - - -void ETH_halt(void) -{ - - EMAC->CTL &= ~(EMAC_CTL_RXON_Msk | EMAC_CTL_TXON_Msk); -} - -unsigned int m_status; - -void EMAC_RX_IRQHandler(void) -{ - m_status = EMAC->INTSTS & 0xFFFF; - EMAC->INTSTS = m_status; - if (m_status & EMAC_INTSTS_RXBEIF_Msk) { - // Shouldn't goes here, unless descriptor corrupted - mbed_error_printf("### RX Bus error [0x%x]\r\n", m_status); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('B', nu_userData); - } - return; - } - EMAC_DISABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('R', nu_userData); - } -} - - -void numaker_eth_trigger_rx(void) -{ - EMAC_ENABLE_INT(EMAC, (EMAC_INTEN_RDUIEN_Msk | EMAC_INTEN_RXGDIEN_Msk)); - ETH_TRIGGER_RX(); -} - -int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf) -{ - unsigned int cur_entry, status; - - cur_entry = EMAC->CRXDSA; - if ((cur_entry == (uint32_t)cur_rx_desc_ptr) && (!(m_status & EMAC_INTSTS_RDUIF_Msk))) { // cur_entry may equal to cur_rx_desc_ptr if RDU occures - return -1; - } - status = cur_rx_desc_ptr->status1; - - if (status & OWNERSHIP_EMAC) { - return -1; - } - - if (status & RXFD_RXGD) { - *buf = cur_rx_desc_ptr->buf; - *len = status & 0xFFFF; - // length of payload should be <= 1514 - if (*len > (NU_ETH_MAX_FLEN - 4)) { - NU_DEBUGF(("%s... unexpected long packet length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); - *len = 0; // Skip this unexpected long packet - } - if (*len == (NU_ETH_MAX_FLEN - 4)) { - NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, *len, *buf)); - } - } - return 0; -} - -void numaker_eth_rx_next(void) -{ - cur_rx_desc_ptr->status1 = OWNERSHIP_EMAC; - cur_rx_desc_ptr = cur_rx_desc_ptr->next; -} - -void EMAC_TX_IRQHandler(void) -{ - unsigned int cur_entry, status; - - status = EMAC->INTSTS & 0xFFFF0000; - EMAC->INTSTS = status; - if (status & EMAC_INTSTS_TXBEIF_Msk) { - // Shouldn't goes here, unless descriptor corrupted - mbed_error_printf("### TX Bus error [0x%x]\r\n", status); - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('B', nu_userData); - } - return; - } - - cur_entry = EMAC->CTXDSA; - - while (cur_entry != (uint32_t)fin_tx_desc_ptr) { - - fin_tx_desc_ptr = fin_tx_desc_ptr->next; - } - - if (nu_eth_txrx_cb != NULL) { - nu_eth_txrx_cb('T', nu_userData); - } -} - -uint8_t *numaker_eth_get_tx_buf(void) -{ - if (cur_tx_desc_ptr->status1 & OWNERSHIP_EMAC) { - return (NULL); - } else { - return (cur_tx_desc_ptr->buf); - } -} - -void numaker_eth_trigger_tx(uint16_t length, void *p) -{ - struct eth_descriptor volatile *desc; - cur_tx_desc_ptr->status2 = (unsigned int)length; - desc = cur_tx_desc_ptr->next; // in case TX is transmitting and overwrite next pointer before we can update cur_tx_desc_ptr - cur_tx_desc_ptr->status1 |= OWNERSHIP_EMAC; - cur_tx_desc_ptr = desc; - - ETH_TRIGGER_TX(); - -} - -int numaker_eth_link_ok(void) -{ - /* first, a dummy read to latch */ - mdio_read(CONFIG_PHY_ADDR, MII_BMSR); - if (mdio_read(CONFIG_PHY_ADDR, MII_BMSR) & BMSR_LSTATUS) { - return 1; - } - return 0; -} - -void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData) -{ - nu_eth_txrx_cb = eth_cb; - nu_userData = userData; -} - -// Override mbed_mac_address of mbed_interface.c to provide ethernet devices with a semi-unique MAC address -void mbed_mac_address(char *mac) -{ - uint32_t uID1; - // Fetch word 0 - uint32_t word0 = *(uint32_t *)0x7F804; // 2KB Data Flash at 0x7F800 - // Fetch word 1 - // we only want bottom 16 bits of word1 (MAC bits 32-47) - // and bit 9 forced to 1, bit 8 forced to 0 - // Locally administered MAC, reduced conflicts - // http://en.wikipedia.org/wiki/MAC_address - uint32_t word1 = *(uint32_t *)0x7F800; // 2KB Data Flash at 0x7F800 - - if (word0 == 0xFFFFFFFF) { // Not burn any mac address at 1st 2 words of Data Flash - // with a semi-unique MAC address from the UUID - /* Enable FMC ISP function */ - SYS_UnlockReg(); - FMC_Open(); - // = FMC_ReadUID(0); - uID1 = FMC_ReadUID(1); - word1 = (uID1 & 0x003FFFFF) | ((uID1 & 0x030000) << 6) >> 8; - word0 = ((FMC_ReadUID(0) >> 4) << 20) | ((uID1 & 0xFF) << 12) | (FMC_ReadUID(2) & 0xFFF); - /* Disable FMC ISP function */ - FMC_Close(); - /* Lock protected registers */ - SYS_LockReg(); - } - - word1 |= 0x00000200; - word1 &= 0x0000FEFF; - - mac[0] = (word1 & 0x0000ff00) >> 8; - mac[1] = (word1 & 0x000000ff); - mac[2] = (word0 & 0xff000000) >> 24; - mac[3] = (word0 & 0x00ff0000) >> 16; - mac[4] = (word0 & 0x0000ff00) >> 8; - mac[5] = (word0 & 0x000000ff); - - NU_DEBUGF(("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); -} - -void numaker_eth_enable_interrupts(void) -{ - EMAC->INTEN |= EMAC_INTEN_RXIEN_Msk | - EMAC_INTEN_TXIEN_Msk ; - NVIC_EnableIRQ(EMAC_RX_IRQn); - NVIC_EnableIRQ(EMAC_TX_IRQn); -} - -void numaker_eth_disable_interrupts(void) -{ - NVIC_DisableIRQ(EMAC_RX_IRQn); - NVIC_DisableIRQ(EMAC_TX_IRQn); -} diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h deleted file mode 100644 index 1766b03..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/TARGET_NUC472/nuc472_eth.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Description: NUC472 EMAC driver header file - */ -#include "NUC472_442.h" -#include "numaker_emac_config.h" -#ifndef _NUC472_ETH_ -#define _NUC472_ETH_ - -/* Generic MII registers. */ - -#define MII_BMCR 0x00 /* Basic mode control register */ -#define MII_BMSR 0x01 /* Basic mode status register */ -#define MII_PHYSID1 0x02 /* PHYS ID 1 */ -#define MII_PHYSID2 0x03 /* PHYS ID 2 */ -#define MII_ADVERTISE 0x04 /* Advertisement control reg */ -#define MII_LPA 0x05 /* Link partner ability reg */ -#define MII_EXPANSION 0x06 /* Expansion register */ -#define MII_DCOUNTER 0x12 /* Disconnect counter */ -#define MII_FCSCOUNTER 0x13 /* False carrier counter */ -#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */ -#define MII_RERRCOUNTER 0x15 /* Receive error counter */ -#define MII_SREVISION 0x16 /* Silicon revision */ -#define MII_RESV1 0x17 /* Reserved... */ -#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */ -#define MII_PHYADDR 0x19 /* PHY address */ -#define MII_RESV2 0x1a /* Reserved... */ -#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */ -#define MII_NCONFIG 0x1c /* Network interface config */ - -/* Basic mode control register. */ -#define BMCR_RESV 0x007f /* Unused... */ -#define BMCR_CTST 0x0080 /* Collision test */ -#define BMCR_FULLDPLX 0x0100 /* Full duplex */ -#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */ -#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */ -#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */ -#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */ -#define BMCR_SPEED100 0x2000 /* Select 100Mbps */ -#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */ -#define BMCR_RESET 0x8000 /* Reset the DP83840 */ - -/* Basic mode status register. */ -#define BMSR_ERCAP 0x0001 /* Ext-reg capability */ -#define BMSR_JCD 0x0002 /* Jabber detected */ -#define BMSR_LSTATUS 0x0004 /* Link status */ -#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */ -#define BMSR_RFAULT 0x0010 /* Remote fault detected */ -#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */ -#define BMSR_RESV 0x07c0 /* Unused... */ -#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ -#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ -#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ -#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ -#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */ - -/* Advertisement control register. */ -#define ADVERTISE_SLCT 0x001f /* Selector bits */ -#define ADVERTISE_CSMA 0x0001 /* Only selector supported */ -#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */ -#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */ -#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */ -#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */ -#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */ -#define ADVERTISE_RESV 0x1c00 /* Unused... */ -#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */ -#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */ -#define ADVERTISE_NPAGE 0x8000 /* Next page bit */ - -#define RX_DESCRIPTOR_NUM NU_RX_RING_LEN//4 //2 // 4: Max Number of Rx Frame Descriptors -#define TX_DESCRIPTOR_NUM NU_TX_RING_LEN//4 //2 // 4: Max number of Tx Frame Descriptors - -#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment - -#define CONFIG_PHY_ADDR 1 - - -// Frame Descriptor's Owner bit -#define OWNERSHIP_EMAC 0x80000000 // 1 = EMAC -//#define OWNERSHIP_CPU 0x7fffffff // 0 = CPU - - - -// Rx Frame Descriptor Status -#define RXFD_RXGD 0x00100000 // Receiving Good Packet Received -#define RXFD_RTSAS 0x00800000 // RX Time Stamp Available - - -// Tx Frame Descriptor's Control bits -#define TXFD_TTSEN 0x08 // Tx Time Stamp Enable -#define TXFD_INTEN 0x04 // Interrupt Enable -#define TXFD_CRCAPP 0x02 // Append CRC -#define TXFD_PADEN 0x01 // Padding Enable - -// Tx Frame Descriptor Status -#define TXFD_TXCP 0x00080000 // Transmission Completion -#define TXFD_TTSAS 0x08000000 // TX Time Stamp Available - -// Tx/Rx buffer descriptor structure -struct eth_descriptor; -struct eth_descriptor { - uint32_t status1; - uint8_t *buf; - uint32_t status2; - struct eth_descriptor *next; -#ifdef TIME_STAMPING - uint32_t backup1; - uint32_t backup2; - uint32_t reserved1; - uint32_t reserved2; -#endif -}; - -#ifdef TIME_STAMPING - -#define ETH_TS_ENABLE() do{EMAC->TSCTL = EMAC_TSCTL_TSEN_Msk;}while(0) -#define ETH_TS_START() do{EMAC->TSCTL |= (EMAC_TSCTL_TSMODE_Msk | EMAC_TSCTL_TSIEN_Msk);}while(0) -s32_t ETH_settime(u32_t sec, u32_t nsec); -s32_t ETH_gettime(u32_t *sec, u32_t *nsec); -s32_t ETH_updatetime(u32_t neg, u32_t sec, u32_t nsec); -s32_t ETH_adjtimex(int ppm); -void ETH_setinc(void); - -#endif - -#endif /* _NUC472_ETH_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.cpp b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.cpp deleted file mode 100644 index 945583e..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.cpp +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * Description: NuMaker EMAC - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -//#define NU_TRACE - -#include "numaker_emac_config.h" -#include "numaker_emac.h" -#include "numaker_eth_hal.h" - -using namespace std::chrono; - -/******************************************************************************** - * - ********************************************************************************/ -#define NU_BUFF_ALIGNMENT 4 -#define PHY_LINKED_STATE 1 -#define PHY_UNLINKED_STATE 0 -#define PACKET_BUFFER_SIZE ( NU_ETH_MAX_FLEN + ((NU_ETH_MAX_FLEN%4) ? (4 - (NU_ETH_MAX_FLEN%4)) : 0) ) //For DMA 4 bytes alignment - -extern "C" void numaker_eth_rx_next(void); -/* \brief Flags for worker thread */ -#define FLAG_TX 1 -#define FLAG_RX 2 -#define FLAG_BUS_RESET 4 - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityNormal) - -#define PHY_TASK_PERIOD 200ms - -NUMAKER_EMAC::NUMAKER_EMAC() : thread(0), hwaddr() -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} - - -/** \brief Ethernet receive interrupt handler - * - * This function handles the receive interrupt. - */ -void NUMAKER_EMAC::rx_isr() -{ - if (thread) { - osThreadFlagsSet(thread, FLAG_RX); - } -} - -void NUMAKER_EMAC::bus_isr() -{ - if (thread) { - osThreadFlagsSet(thread, FLAG_BUS_RESET); - } -} - -void NUMAKER_EMAC::tx_isr() -{ - /* No-op at this stage */ -} - -void NUMAKER_EMAC::ethernet_callback(char event, void *param) -{ - NUMAKER_EMAC *enet = static_cast(param); - switch (event) { - case 'R': //For RX event - enet->rx_isr(); - break; - case 'T': //For TX event - enet->tx_isr(); - break; - case 'B': // For BUS event - enet->bus_isr(); - default: - break; - } -} - - -/** - * In this function, the hardware should be initialized. - */ -bool NUMAKER_EMAC::low_level_init_successful() -{ - /* Init ETH */ - - mbed_mac_address((char *)hwaddr); - printf("mac address %02x-%02x-%02x-%02x-%02x-%02x \r\n", hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]); - /* Enable clock & set EMAC configuration */ - /* Enable MAC and DMA transmission and reception */ - numaker_eth_init(hwaddr); - - numaker_eth_set_cb(&NUMAKER_EMAC::ethernet_callback, this); - - return true; -} - - -int NUMAKER_EMAC::low_level_input(emac_mem_buf_t **buf) -{ - uint16_t len = 0; - uint8_t *buffer; - uint32_t bufferoffset = 0; - uint32_t byteslefttocopy = 0; - emac_mem_buf_t *q; - uint32_t payloadoffset = 0; - - /* get received frame */ - if (numaker_eth_get_rx_buf(&len, &buffer) != 0) { - return -1; - } - byteslefttocopy = len; - - if (len > 0) { - /* Allocate a memory buffer chain from buffer pool */ - *buf = memory_manager->alloc_pool(len, 0); - } - NU_DEBUGF(("%s... length=%d, buf=0x%x\r\n", __FUNCTION__, len, *buf)); - if (*buf != NULL) { - bufferoffset = 0; - for (q = *buf; q != NULL; q = memory_manager->get_next(q)) { - byteslefttocopy = memory_manager->get_len(q); - payloadoffset = 0; - NU_DEBUGF(("offset=[%d], bytes-to-copy[%d]\r\n", bufferoffset, byteslefttocopy)); - /* Copy data in pbuf */ - memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, byteslefttocopy); - - bufferoffset = bufferoffset + byteslefttocopy; - } - } - - return 0; -} - - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ - -void NUMAKER_EMAC::thread_function(void *pvParameters) -{ - static struct NUMAKER_EMAC *nu_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_BUS_RESET, osFlagsWaitAny, osWaitForever); - - if (flags & FLAG_RX) { - nu_enet->packet_rx(); - } - if (flags & FLAG_BUS_RESET) { - NU_DEBUGF(("BUS error and reset bus\r\n")); - nu_enet->bus_reset(); - } - } -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the LWIP core. - */ -void NUMAKER_EMAC::packet_rx() -{ - /* move received packet into a new buf */ - while (1) { - emac_mem_buf_t *p = NULL; - if (low_level_input(&p) < 0) { - break; - } - if (p) { - NU_DEBUGF(("%s ... p=0x%x\r\n", __FUNCTION__, p)); - emac_link_input_cb(p); - } - numaker_eth_rx_next(); - } - numaker_eth_trigger_rx(); - -} - - -/** - * This function should do the actual transmission of the packet. The packet is - * contained in the buf that is passed to the function. This buf - * might be chained. - * - * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return true if the packet could be sent - * false value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become available since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ -bool NUMAKER_EMAC::link_out(emac_mem_buf_t *buf) -{ - bool result = false; - emac_mem_buf_t *q; - uint8_t *buffer = NULL; - uint32_t framelength = 0; - uint32_t bufferoffset = 0; - uint32_t byteslefttocopy = 0; - uint32_t payloadoffset = 0; - - /* Get exclusive access */ - TXLockMutex.lock(); - buffer = numaker_eth_get_tx_buf(); - NU_DEBUGF(("%s ... buffer=0x%x\r\n", __FUNCTION__, buffer)); - if (buffer == NULL) { - goto error; - } - /* copy frame from buf to driver buffers */ - for (q = buf; q != NULL; q = memory_manager->get_next(q)) { - - /* Get bytes in current lwIP buffer */ - byteslefttocopy = memory_manager->get_len(q); - payloadoffset = 0; - NU_DEBUGF(("offset=%d, bytes-to-copy=%d\r\n", bufferoffset, byteslefttocopy)); - /* Check if the length of data to copy is bigger than Tx buffer size*/ - while ((byteslefttocopy + bufferoffset) > PACKET_BUFFER_SIZE) { - /* Copy data to Tx buffer*/ - memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, (PACKET_BUFFER_SIZE - bufferoffset)); - - /* Point to next descriptor */ - numaker_eth_trigger_tx(PACKET_BUFFER_SIZE, NULL); - buffer = numaker_eth_get_tx_buf(); - if (buffer == NULL) { - goto error; - } - - byteslefttocopy = byteslefttocopy - (PACKET_BUFFER_SIZE - bufferoffset); - payloadoffset = payloadoffset + (PACKET_BUFFER_SIZE - bufferoffset); - framelength = framelength + (PACKET_BUFFER_SIZE - bufferoffset); - bufferoffset = 0; - } - - /* Copy the remaining bytes */ - memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy); - bufferoffset = bufferoffset + byteslefttocopy; - framelength = framelength + byteslefttocopy; - } - - /* Prepare transmit descriptors to give to DMA */ - numaker_eth_trigger_tx(framelength, NULL); - - result = true; - -error: - - memory_manager->free(buf); - - /* Restore access */ - TXLockMutex.unlock(); - - return result; -} - - -void NUMAKER_EMAC::phy_task() -{ - - // Get current status - int state; - state = numaker_eth_link_ok(); - - - if ((state & PHY_LINKED_STATE) && !(phy_state & PHY_LINKED_STATE)) { - NU_DEBUGF(("Link Up\r\n")); - if (emac_link_state_cb) { - emac_link_state_cb(true); - } - } else if (!(state & PHY_LINKED_STATE) && (phy_state & PHY_LINKED_STATE)) { - NU_DEBUGF(("Link Down\r\n")); - if (emac_link_state_cb) { - emac_link_state_cb(false); - } - } - phy_state = state; - -} - -bool NUMAKER_EMAC::power_up() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - /* Worker thread */ - thread = create_new_thread("numaker_emac_thread", &NUMAKER_EMAC::thread_function, this, THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb); - - /* PHY monitoring task */ - phy_state = PHY_UNLINKED_STATE; - - phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &NUMAKER_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - numaker_eth_enable_interrupts(); - return true; -} - -bool NUMAKER_EMAC::bus_reset() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - numaker_eth_enable_interrupts(); - return true; -} - - -uint32_t NUMAKER_EMAC::get_mtu_size() const -{ - return NU_ETH_MTU_SIZE; -} - -uint32_t NUMAKER_EMAC::get_align_preference() const -{ - return NU_BUFF_ALIGNMENT; -} - -void NUMAKER_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, NU_ETH_IF_NAME, (size < sizeof(NU_ETH_IF_NAME)) ? size : sizeof(NU_ETH_IF_NAME)); -} - -uint8_t NUMAKER_EMAC::get_hwaddr_size() const -{ - return NU_HWADDR_SIZE; -} - -bool NUMAKER_EMAC::get_hwaddr(uint8_t *addr) const -{ - mbed_mac_address((char *)addr); - return true; -} - -void NUMAKER_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, sizeof hwaddr); - numaker_set_mac_addr(const_cast(addr)); -} - -void NUMAKER_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void NUMAKER_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void NUMAKER_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void NUMAKER_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void NUMAKER_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - - -void NUMAKER_EMAC::power_down() -{ - /* No-op at this stage */ -} - -void NUMAKER_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - - -NUMAKER_EMAC &NUMAKER_EMAC::get_instance() -{ - static NUMAKER_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return NUMAKER_EMAC::get_instance(); -} - - - - diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.h b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.h deleted file mode 100644 index c7c4955..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac.h +++ /dev/null @@ -1,173 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NUMAKER_EMAC_H_ -#define NUMAKER_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Mutex.h" - -class NUMAKER_EMAC : public EMAC { -public: - NUMAKER_EMAC(); - - static NUMAKER_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - bool low_level_init_successful(); - void tx_isr(); - void rx_isr(); - void bus_isr(); - void packet_rx(); - bool bus_reset(); - int low_level_input(emac_mem_buf_t **buf); - static void thread_function(void *pvParameters); - void phy_task(); - static void ethernet_callback(char event, void *param); - - mbed_rtos_storage_thread_t thread_cb; - osThreadId_t thread; /**< Processing thread */ - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - int phy_task_handle; /**< Handle for phy task event */ - int phy_state; - uint8_t hwaddr[6]; -}; - -#endif /* NUMAKER_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac_config.h b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac_config.h deleted file mode 100644 index 7bb83c3..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_emac_config.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * - * Description: NuMaker EMAC Config header file - */ - -#ifndef NUMAKER_EMAC_CONFIG_H__ -#define NUMAKER_EMAC_CONFIG_H__ - -#define NU_RX_RING_LEN (8) -#define NU_TX_RING_LEN (4) - -#define NU_ETH_MAX_FLEN (1518) - -#define NU_HWADDR_SIZE (6) - -#define NU_ETH_MTU_SIZE 1500 -#define NU_ETH_IF_NAME "nu" - -#define THREAD_STACKSIZE 512 - -#endif // #define NUMAKER_EMAC_CONFIG_H__ - diff --git a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_eth_hal.h b/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_eth_hal.h deleted file mode 100644 index e84ee60..0000000 --- a/features/netsocket/emac-drivers/TARGET_NUVOTON_EMAC/numaker_eth_hal.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2018 Nuvoton Technology Corp. - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Description: NuMaker EMAC HAL header file - */ - -#ifndef NUMAKER_ETH_HAL_ -#define NUMAKER_ETH_HAL_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#ifdef NU_TRACE -#define NU_DEBUGF(x) { printf x; } -#else -#define NU_DEBUGF(x) -#endif - -typedef void (* eth_callback_t) (char, void*); -void mbed_mac_address(char *mac); -void numaker_eth_init(uint8_t *mac_addr); -void numaker_eth_trigger_rx(void); -int numaker_eth_get_rx_buf(uint16_t *len, uint8_t **buf); -uint8_t *numaker_eth_get_tx_buf(void); -void numaker_eth_trigger_tx(uint16_t length, void *p); -int numaker_eth_link_ok(void); -void numaker_eth_set_cb(eth_callback_t eth_cb, void *userData); -void numaker_set_mac_addr(uint8_t *addr); -void numaker_eth_enable_interrupts(void); -void numaker_eth_disable_interrupts(void); - -#ifdef __cplusplus -} -#endif - -#endif /* NUMAKER_ETH_HAL_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c deleted file mode 100644 index 2f6e27f..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/TARGET_MIMXRT1050_EVK/hardware_init.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "fsl_gpio.h" -#include "fsl_iomuxc.h" -#include "fsl_clock.h" -#include "mbed_wait_api.h" - -/******************************************************************************* - * Code - ******************************************************************************/ -static void BOARD_InitModuleClock(void) -{ - const clock_enet_pll_config_t config = {true, false, 1}; - CLOCK_InitEnetPll(&config); -} - -void kinetis_init_eth_hardware(void) -{ - gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; - - CLOCK_EnableClock(kCLOCK_Iomuxc); /* iomuxc clock (iomuxc_clk_enable): 0x03u */ - - IOMUXC_SetPinMux( - IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 is configured as GPIO1_IO09 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 is configured as GPIO1_IO10 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 is configured as ENET_RX_DATA00 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 is configured as ENET_RX_DATA01 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 is configured as ENET_RX_EN */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 is configured as ENET_TX_DATA00 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 is configured as ENET_TX_DATA01 */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 is configured as ENET_TX_EN */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 is configured as ENET_REF_CLK */ - 1U); /* Software Input On Field: Force input path of pad GPIO_B1_10 */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 is configured as ENET_RX_ER */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 is configured as ENET_MDC */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinMux( - IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 is configured as ENET_MDIO */ - 0U); /* Software Input On Field: Input Path is determined by functionality */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, /* GPIO_AD_B0_09 PAD functional properties : */ - 0xB0A9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: medium(100MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_AD_B0_10_GPIO1_IO10, /* GPIO_AD_B0_10 PAD functional properties : */ - 0xB0A9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: medium(100MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_04_ENET_RX_DATA00, /* GPIO_B1_04 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_05_ENET_RX_DATA01, /* GPIO_B1_05 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_06_ENET_RX_EN, /* GPIO_B1_06 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_07_ENET_TX_DATA00, /* GPIO_B1_07 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_08_ENET_TX_DATA01, /* GPIO_B1_08 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_09_ENET_TX_EN, /* GPIO_B1_09 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_10_ENET_REF_CLK, /* GPIO_B1_10 PAD functional properties : */ - 0x31u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/6 - Speed Field: low(50MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Disabled - Pull / Keep Select Field: Keeper - Pull Up / Down Config. Field: 100K Ohm Pull Down - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_B1_11_ENET_RX_ER, /* GPIO_B1_11 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_EMC_40_ENET_MDC, /* GPIO_EMC_40 PAD functional properties : */ - 0xB0E9u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: max(200MHz) - Open Drain Enable Field: Open Drain Disabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - IOMUXC_SetPinConfig( - IOMUXC_GPIO_EMC_41_ENET_MDIO, /* GPIO_EMC_41 PAD functional properties : */ - 0xB829u); /* Slew Rate Field: Fast Slew Rate - Drive Strength Field: R0/5 - Speed Field: low(50MHz) - Open Drain Enable Field: Open Drain Enabled - Pull / Keep Enable Field: Pull/Keeper Enabled - Pull / Keep Select Field: Pull - Pull Up / Down Config. Field: 100K Ohm Pull Up - Hyst. Enable Field: Hysteresis Disabled */ - - - BOARD_InitModuleClock(); - - IOMUXC_EnableMode(IOMUXC_GPR, kIOMUXC_GPR_ENET1TxClkOutputDir, true); - - GPIO_PinInit(GPIO1, 9, &gpio_config); - GPIO_PinInit(GPIO1, 10, &gpio_config); - /* pull up the ENET_INT before RESET. */ - GPIO_WritePinOutput(GPIO1, 10, 1); - GPIO_WritePinOutput(GPIO1, 9, 0); - wait_us(1 * 1000); - GPIO_WritePinOutput(GPIO1, 9, 1); -} - -/******************************************************************************* - * EOF - ******************************************************************************/ - - diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp deleted file mode 100644 index f69d524..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * Copyright (c) 2017 ARM Limited - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -#include "fsl_phy.h" - -#include "imx_emac_config.h" -#include "imx_emac.h" -#include "mbed_power_mgmt.h" - -using namespace std::chrono; - -enet_handle_t g_handle; -// RX packet buffer pointers -emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; -// TX packet buffer pointers -emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; -// RX packet payload pointers -uint32_t *rx_ptr[ENET_RX_RING_LEN]; - -/******************************************************************************** - * Internal data - ********************************************************************************/ -#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) -#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) - -extern "C" void kinetis_init_eth_hardware(void); - -/* \brief Flags for worker thread */ -#define FLAG_TX 1 -#define FLAG_RX 2 - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityNormal) - -#define PHY_TASK_PERIOD 200ms - -Kinetis_EMAC::Kinetis_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} -/******************************************************************************** - * Buffer management - ********************************************************************************/ -/* - * This function will queue a new receive buffer - */ -static void update_read_buffer(uint8_t *buf) -{ - if (buf != NULL) { - g_handle.rxBdCurrent[0]->buffer = buf; - } - - /* Ensures buffer pointer is written before control. */ - __DMB(); - - /* Clears status. */ - g_handle.rxBdCurrent[0]->control &= ENET_BUFFDESCRIPTOR_RX_WRAP_MASK; - - /* Sets the receive buffer descriptor with the empty flag. */ - g_handle.rxBdCurrent[0]->control |= ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK; - - /* Increases the buffer descriptor to the next one. */ - if (g_handle.rxBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_RX_WRAP_MASK) { - g_handle.rxBdCurrent[0] = g_handle.rxBdBase[0]; - } else { - g_handle.rxBdCurrent[0]++; - } - - /* Ensures descriptor is written before kicking hardware. */ - __DSB(); - - /* Actives the receive buffer descriptor. */ - ENET->RDAR = ENET_RDAR_RDAR_MASK; -} - -/** \brief Free TX buffers that are complete - */ -void Kinetis_EMAC::tx_reclaim() -{ - /* Get exclusive access */ - TXLockMutex.lock(); - - // Traverse all descriptors, looking for the ones modified by the uDMA - while ((tx_consume_index != tx_produce_index) && - (!(g_handle.txBdDirty[0]->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK))) { - memory_manager->free(tx_buff[tx_consume_index % ENET_TX_RING_LEN]); - if (g_handle.txBdDirty[0]->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { - g_handle.txBdDirty[0] = g_handle.txBdBase[0]; - } else { - g_handle.txBdDirty[0]++; - } - - tx_consume_index += 1; - xTXDCountSem.release(); - } - - /* Restore access */ - TXLockMutex.unlock(); -} - -/** \brief Ethernet receive interrupt handler - * - * This function handles the receive interrupt. - */ -void Kinetis_EMAC::rx_isr() -{ - if (thread) { - osThreadFlagsSet(thread, FLAG_RX); - } -} - -void Kinetis_EMAC::tx_isr() -{ - osThreadFlagsSet(thread, FLAG_TX); -} - -void Kinetis_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param) -{ - Kinetis_EMAC *enet = static_cast(param); - switch (event) { - case kENET_RxEvent: - enet->rx_isr(); - break; - case kENET_TxEvent: - enet->tx_isr(); - break; - default: - break; - } -} - - -/** \brief Low level init of the MAC and PHY. - */ -bool Kinetis_EMAC::low_level_init_successful() -{ - uint8_t i; - uint32_t sysClock; - phy_speed_t phy_speed; - phy_duplex_t phy_duplex; - uint32_t phyAddr = 0; - enet_config_t config; - - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rx_desc_start_addr[ENET_RX_RING_LEN], ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t tx_desc_start_addr[ENET_TX_RING_LEN], ENET_BUFF_ALIGNMENT); - - /* Create buffers for each receive BD */ - for (i = 0; i < ENET_RX_RING_LEN; i++) { - rx_buff[i] = memory_manager->alloc_heap(ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), - ENET_BUFF_ALIGNMENT); - if (NULL == rx_buff[i]) { - return false; - } - - rx_ptr[i] = (uint32_t *)memory_manager->get_ptr(rx_buff[i]); - SCB_InvalidateDCache_by_Addr(rx_ptr[i], ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT)); - } - - tx_consume_index = tx_produce_index = 0; - - /* prepare the buffer configuration. */ - enet_buffer_config_t buffCfg = { - ENET_RX_RING_LEN, - ENET_TX_RING_LEN, - ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), - 0, - (volatile enet_rx_bd_struct_t *)rx_desc_start_addr, - (volatile enet_tx_bd_struct_t *)tx_desc_start_addr, - (uint8_t *) &rx_ptr, - NULL, - }; - - kinetis_init_eth_hardware(); - - sysClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); - - ENET_GetDefaultConfig(&config); - - if (PHY_Init(ENET, phyAddr, sysClock) != kStatus_Success) { - return false; - } - - /* Get link information from PHY */ - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); - /* Change the MII speed and duplex for actual link status. */ - config.miiSpeed = (enet_mii_speed_t)phy_speed; - config.miiDuplex = (enet_mii_duplex_t)phy_duplex; - config.interrupt = kENET_RxFrameInterrupt | kENET_TxFrameInterrupt; - config.rxMaxFrameLen = ENET_ETH_MAX_FLEN; - config.macSpecialConfig = kENET_ControlFlowControlEnable; - config.txAccelerConfig = 0; - config.rxAccelerConfig = kENET_RxAccelMacCheckEnabled; - ENET_Init(ENET, &g_handle, &config, &buffCfg, hwaddr, sysClock); - - ENET_SetCallback(&g_handle, &Kinetis_EMAC::ethernet_callback, this); - ENET_ActiveRead(ENET); - - return true; -} - -/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. - * - * \param[in] idx index of packet to be read - * \return a emac_mem_buf_t filled with the received packet (including MAC header) - */ -emac_mem_buf_t *Kinetis_EMAC::low_level_input(int idx) -{ - volatile enet_rx_bd_struct_t *bdPtr = g_handle.rxBdCurrent[0]; - emac_mem_buf_t *p = NULL; - emac_mem_buf_t *temp_rxbuf = NULL; - uint32_t length = 0; - const uint16_t err_mask = ENET_BUFFDESCRIPTOR_RX_TRUNC_MASK | ENET_BUFFDESCRIPTOR_RX_CRC_MASK | - ENET_BUFFDESCRIPTOR_RX_NOOCTET_MASK | ENET_BUFFDESCRIPTOR_RX_LENVLIOLATE_MASK; - -#ifdef LOCK_RX_THREAD - /* Get exclusive access */ - TXLockMutex.lock(); -#endif - - /* Determine if a frame has been received */ - if ((bdPtr->control & err_mask) != 0) { - /* Re-use the same buffer in case of error */ - update_read_buffer(NULL); - } else { - /* A packet is waiting, get length */ - length = bdPtr->length; - - /* Zero-copy */ - p = rx_buff[idx]; - SCB_InvalidateDCache_by_Addr(rx_ptr[idx], length); - memory_manager->set_len(p, length); - - /* Attempt to queue new buffer */ - temp_rxbuf = memory_manager->alloc_heap(ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT), - ENET_BUFF_ALIGNMENT); - if (NULL == temp_rxbuf) { - /* Re-queue the same buffer */ - update_read_buffer(NULL); - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - - return NULL; - } - - rx_buff[idx] = temp_rxbuf; - rx_ptr[idx] = (uint32_t *)memory_manager->get_ptr(rx_buff[idx]); - SCB_InvalidateDCache_by_Addr(rx_ptr[idx], ENET_ALIGN(ENET_ETH_MAX_FLEN, ENET_BUFF_ALIGNMENT)); - - update_read_buffer((uint8_t *)rx_ptr[idx]); - } - -#ifdef LOCK_RX_THREAD - osMutexRelease(TXLockMutex); -#endif - - return p; -} - -/** \brief Attempt to read a packet from the EMAC interface. - * - * \param[in] idx index of packet to be read - */ -void Kinetis_EMAC::input(int idx) -{ - emac_mem_buf_t *p; - - /* move received packet into a new buf */ - p = low_level_input(idx); - if (p == NULL) { - return; - } - - emac_link_input_cb(p); -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void Kinetis_EMAC::thread_function(void *pvParameters) -{ - struct Kinetis_EMAC *kinetis_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); - - MBED_ASSERT(!(flags & osFlagsError)); - - if (flags & FLAG_RX) { - kinetis_enet->packet_rx(); - } - - if (flags & FLAG_TX) { - kinetis_enet->packet_tx(); - } - } -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the LWIP core. - */ -void Kinetis_EMAC::packet_rx() -{ - static int idx = 0; - - while ((g_handle.rxBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_RX_EMPTY_MASK) == 0) { - input(idx); - idx = (idx + 1) % ENET_RX_RING_LEN; - } -} - -/** \brief Transmit cleanup task - * - * This task is called when a transmit interrupt occurs and - * reclaims the buffer and descriptor used for the packet once - * the packet has been transferred. - */ -void Kinetis_EMAC::packet_tx() -{ - tx_reclaim(); -} - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent - */ -bool Kinetis_EMAC::link_out(emac_mem_buf_t *buf) -{ - // If buffer is chained or not aligned then make a contiguous aligned copy of it - if (memory_manager->get_next(buf) || - reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { - emac_mem_buf_t *copy_buf; - copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); - if (NULL == copy_buf) { - memory_manager->free(buf); - return false; - } - - // Copy to new buffer and free original - memory_manager->copy(copy_buf, buf); - memory_manager->free(buf); - buf = copy_buf; - } - - SCB_CleanDCache_by_Addr(static_cast(memory_manager->get_ptr(buf)), memory_manager->get_len(buf)); - - /* Check if a descriptor is available for the transfer (wait 10ms before dropping the buffer) */ - if (!xTXDCountSem.try_acquire_for(10)) { - memory_manager->free(buf); - return false; - } - - /* Get exclusive access */ - TXLockMutex.lock(); - - /* Save the buffer so that it can be freed when transmit is done */ - tx_buff[tx_produce_index % ENET_TX_RING_LEN] = buf; - tx_produce_index += 1; - - /* Setup transfers */ - g_handle.txBdCurrent[0]->buffer = static_cast(memory_manager->get_ptr(buf)); - g_handle.txBdCurrent[0]->length = memory_manager->get_len(buf); - /* Ensures buffer and length is written before control. */ - __DMB(); - g_handle.txBdCurrent[0]->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); - - /* Increase the buffer descriptor address. */ - if (g_handle.txBdCurrent[0]->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) { - g_handle.txBdCurrent[0] = g_handle.txBdBase[0]; - } else { - g_handle.txBdCurrent[0]++; - } - - /* Ensures descriptor is written before kicking hardware. */ - __DSB(); - - /* Active the transmit buffer descriptor. */ - ENET->TDAR = ENET_TDAR_TDAR_MASK; - - /* Restore access */ - TXLockMutex.unlock(); - - return true; -} - -/******************************************************************************* - * PHY task: monitor link -*******************************************************************************/ - -#define STATE_UNKNOWN (-1) -#define STATE_LINK_DOWN (0) -#define STATE_LINK_UP (1) - -void Kinetis_EMAC::phy_task() -{ - uint32_t phyAddr = BOARD_ENET_PHY_ADDR; - - // Get current status - PHY_STATE crt_state; - bool connection_status; - PHY_GetLinkStatus(ENET, phyAddr, &connection_status); - - if (connection_status) { - crt_state.connected = STATE_LINK_UP; - } else { - crt_state.connected = STATE_LINK_DOWN; - } - - if (crt_state.connected == STATE_LINK_UP) { - if (prev_state.connected != STATE_LINK_UP) { - PHY_AutoNegotiation(ENET, phyAddr); - } - - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); - - if (prev_state.connected != STATE_LINK_UP || crt_state.speed != prev_state.speed) { - /* Poke the registers*/ - ENET_SetMII(ENET, (enet_mii_speed_t)crt_state.speed, (enet_mii_duplex_t)crt_state.duplex); - } - } - - // Compare with previous state - if (crt_state.connected != prev_state.connected && emac_link_state_cb) { - emac_link_state_cb(crt_state.connected); - } - - prev_state = crt_state; -} - -bool Kinetis_EMAC::power_up() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - // Can't enter deep sleep as long as Ethernet is active - sleep_manager_lock_deep_sleep(); - - /* Worker thread */ - thread = create_new_thread("Kinetis_EMAC_thread", &Kinetis_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); - - /* Trigger thread to deal with any RX packets that arrived before thread was started */ - rx_isr(); - - /* PHY monitoring task */ - prev_state.connected = STATE_LINK_DOWN; - prev_state.speed = (phy_speed_t)STATE_UNKNOWN; - prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; - - mbed::mbed_event_queue()->call(mbed::callback(this, &Kinetis_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &Kinetis_EMAC::phy_task)); - - return true; -} - -uint32_t Kinetis_EMAC::get_mtu_size() const -{ - return KINETIS_ETH_MTU_SIZE; -} - -uint32_t Kinetis_EMAC::get_align_preference() const -{ - return ENET_BUFF_ALIGNMENT; -} - -void Kinetis_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, KINETIS_ETH_IF_NAME, (size < sizeof(KINETIS_ETH_IF_NAME)) ? size : sizeof(KINETIS_ETH_IF_NAME)); -} - -uint8_t Kinetis_EMAC::get_hwaddr_size() const -{ - return KINETIS_HWADDR_SIZE; -} - -bool Kinetis_EMAC::get_hwaddr(uint8_t *addr) const -{ - return false; -} - -void Kinetis_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, sizeof hwaddr); - ENET_SetMacAddr(ENET, const_cast(addr)); -} - -void Kinetis_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void Kinetis_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void Kinetis_EMAC::add_multicast_group(const uint8_t *addr) -{ - ENET_AddMulticastGroup(ENET, const_cast(addr)); -} - -void Kinetis_EMAC::remove_multicast_group(const uint8_t *addr) -{ - // ENET HAL doesn't reference count - ENET_LeaveMulticastGroup just maps - // address to filter bit, and clears that bit, even if shared by other - // addresses. So don't attempt anything for now. -} - -void Kinetis_EMAC::set_all_multicast(bool all) -{ - if (all) { - ENET->GAUR = 0xFFFFFFFFu; - ENET->GALR = 0xFFFFFFFFu; - } -} - -void Kinetis_EMAC::power_down() -{ - // Ethernet went down, can enter deep sleep - sleep_manager_unlock_deep_sleep(); -} - -void Kinetis_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - - -Kinetis_EMAC &Kinetis_EMAC::get_instance() -{ - static Kinetis_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return Kinetis_EMAC::get_instance(); -} - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */ - diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h deleted file mode 100644 index 82b588b..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac.h +++ /dev/null @@ -1,182 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef KINETIS_EMAC_H_ -#define KINETIS_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -class Kinetis_EMAC : public EMAC { -public: - Kinetis_EMAC(); - - static Kinetis_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - bool low_level_init_successful(); - void rx_isr(); - void tx_isr(); - void packet_rx(); - void packet_tx(); - void tx_reclaim(); - void input(int idx); - emac_mem_buf_t *low_level_input(int idx); - static void thread_function(void* pvParameters); - void phy_task(); - static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *param); - - mbed_rtos_storage_thread_t thread_cb; - osThreadId_t thread; /**< Processing thread */ - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ - uint8_t tx_consume_index, tx_produce_index; /**< TX buffers ring */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - int phy_task_handle; /**< Handle for phy task event */ - struct PHY_STATE { - int connected; - phy_speed_t speed; - phy_duplex_t duplex; - }; - PHY_STATE prev_state; - uint8_t hwaddr[KINETIS_HWADDR_SIZE]; -}; - -#endif /* KINETIS_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h deleted file mode 100644 index a56fe41..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/imx_emac_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * o Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * - * o Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef KINETIS_EMAC_CONFIG_H__ -#define KINETIS_EMAC_CONFIG_H__ - -#include "fsl_enet.h" - -#define ENET_RX_RING_LEN MBED_CONF_KINETIS_EMAC_RX_RING_LEN -#define ENET_TX_RING_LEN MBED_CONF_KINETIS_EMAC_TX_RING_LEN - -#define ENET_ETH_MAX_FLEN (1522) // recommended size for a VLAN frame - -#define KINETIS_HWADDR_SIZE (6) - -#define KINETIS_ETH_MTU_SIZE 1500 -#define KINETIS_ETH_IF_NAME "en" - -#define THREAD_STACKSIZE 512 - -#endif // #define KINETIS_EMAC_CONFIG_H__ - diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json deleted file mode 100644 index 2e1ef2e..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_IMX/mbed_lib.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "kinetis-emac", - "config": { - "rx-ring-len": 16, - "tx-ring-len": 8 - } -} diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp deleted file mode 100644 index 76cbe38..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp +++ /dev/null @@ -1,941 +0,0 @@ -/********************************************************************** -* $Id$ lpc17_emac.c 2011-11-20 -*//** -* @file lpc17_emac.c -* @brief LPC17 ethernet driver for LWIP -* @version 1.0 -* @date 20. Nov. 2011 -* @author NXP MCU SW Application Team -* -* Copyright(C) 2011, NXP Semiconductor -* All rights reserved. -* -*********************************************************************** -* Software that is described herein is for illustrative purposes only -* which provides customers with programming information regarding the -* products. This software is supplied "AS IS" without any warranties. -* NXP Semiconductors assumes no responsibility or liability for the -* use of the software, conveys no license or title under any patent, -* copyright, or mask work right to the product. NXP Semiconductors -* reserves the right to make changes in the software without -* notification. NXP Semiconductors also make no representation or -* warranty that such application will be suitable for the specified -* use without further testing or modification. -**********************************************************************/ - -#include -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" - -#include "lpc_emac_config.h" -#include "lpc17_emac.h" -#include "lpc17xx_emac.h" -#include "lpc_phy.h" -#include "mbed_interface.h" - -#ifndef LPC_EMAC_RMII -#error LPC_EMAC_RMII is not defined! -#endif - -#if LPC_NUM_BUFF_TXDESCS < 2 -#error LPC_NUM_BUFF_TXDESCS must be at least 2 -#endif - -#if LPC_NUM_BUFF_RXDESCS < 3 -#error LPC_NUM_BUFF_RXDESCS must be at least 3 -#endif - -/** @defgroup lwip17xx_emac_DRIVER lpc17 EMAC driver for LWIP - * @ingroup lwip_emac - * - * @{ - */ - -/** \brief Driver transmit and receive thread priorities - * - * Thread priorities for receive thread and TX cleanup thread. Alter - * to prioritize receive or transmit bandwidth. In a heavily loaded - * system or with LEIP_DEBUG enabled, the priorities might be better - * the same. */ -#define RX_PRIORITY (osPriorityNormal) -#define TX_PRIORITY (osPriorityNormal) -#define PHY_PRIORITY (osPriorityNormal) - -/** \brief Debug output formatter lock define - * - * When using FreeRTOS and with LWIP_DEBUG enabled, enabling this - * define will allow RX debug messages to not interleave with the - * TX messages (so they are actually readable). Not enabling this - * define when the system is under load will cause the output to - * be unreadable. There is a small tradeoff in performance for this - * so use it only for debug. */ -//#define LOCK_RX_THREAD - -/** \brief Receive group interrupts - */ -#define RXINTGROUP (EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE) - -/** \brief Transmit group interrupts - */ -#define TXINTGROUP (EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE) - -/** \brief Signal used for ethernet ISR to signal packet_rx() thread. - */ -#define RX_SIGNAL 1 - - /** \brief Structure of a TX/RX descriptor - */ -typedef struct -{ - volatile uint32_t packet; /**< Pointer to buffer */ - volatile uint32_t control; /**< Control word */ -} LPC_TXRX_DESC_T; - -/** \brief Structure of a RX status entry - */ -typedef struct -{ - volatile uint32_t statusinfo; /**< RX status word */ - volatile uint32_t statushashcrc; /**< RX hash CRC */ -} LPC_TXRX_STATUS_T; - -/* LPC EMAC driver data structure */ -struct lpc_enetdata { - /* prxs must be 8 byte aligned! */ - LPC_TXRX_STATUS_T prxs[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX statuses */ - LPC_TXRX_DESC_T ptxd[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX descriptor list */ - LPC_TXRX_STATUS_T ptxs[LPC_NUM_BUFF_TXDESCS]; /**< Pointer to TX statuses */ - LPC_TXRX_DESC_T prxd[LPC_NUM_BUFF_RXDESCS]; /**< Pointer to RX descriptor list */ - emac_mem_buf_t *rxb[LPC_NUM_BUFF_RXDESCS]; /**< RX pbuf pointer list, zero-copy mode */ - uint32_t rx_fill_desc_index; /**< RX descriptor next available index */ - volatile uint32_t rx_free_descs; /**< Count of free RX descriptors */ - emac_mem_buf_t *txb[LPC_NUM_BUFF_TXDESCS]; /**< TX pbuf pointer list, zero-copy mode */ - uint32_t lpc_last_tx_idx; /**< TX last descriptor index, zero-copy mode */ - uint32_t lpc_reserved_tx_num; /**< Number of reserved TX descriptors, zero-copy mode */ -}; - -#if defined(TARGET_LPC1768) -/** \brief Group LPC17xx processors into one definition - */ -#define TARGET_LPC17XX -#endif - -#if defined(TARGET_LPC17XX) -# if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_ARM) -# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) -# endif -#endif - -#ifndef ETHMEM_SECTION -#define ETHMEM_SECTION -#endif - -/** \brief LPC EMAC driver work data - */ -#if defined (__ICCARM__) -#pragma location = ".ethusbram" -#pragma data_alignment = 8 -#endif -ETHMEM_SECTION struct lpc_enetdata lpc_enetdata; - -#if defined (__ICCARM__) -#pragma location = ".ethusbram" -#pragma data_alignment = 8 -#endif -ETHMEM_SECTION uint8_t rx_thread_stack[DEFAULT_THREAD_STACKSIZE]; - -#if defined (__ICCARM__) -#pragma location = ".ethusbram" -#pragma data_alignment = 8 -#endif -ETHMEM_SECTION uint8_t tx_clean_thread_stack[DEFAULT_THREAD_STACKSIZE]; - -#if defined (__ICCARM__) -#pragma location = ".ethusbram" -#pragma data_alignment = 8 -#endif -ETHMEM_SECTION uint8_t phy_thread_stack[DEFAULT_THREAD_STACKSIZE]; - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, void *stack_ptr, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = stack_ptr; - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} - -/** \brief Queues a memory buffer into the RX descriptor list - * - * \param[in] p Pointer to buffer to queue - */ -void LPC17_EMAC::lpc_rxqueue_pbuf(emac_mem_buf_t *p) -{ - uint32_t idx; - - /* Get next free descriptor index */ - idx = lpc_enetdata.rx_fill_desc_index; - - /* Setup descriptor and clear statuses */ - lpc_enetdata.prxd[idx].control = EMAC_RCTRL_INT | ((uint32_t) (memory_manager->get_len(p) - 1)); - lpc_enetdata.prxd[idx].packet = (uint32_t) memory_manager->get_ptr(p); - lpc_enetdata.prxs[idx].statusinfo = 0xFFFFFFFF; - lpc_enetdata.prxs[idx].statushashcrc = 0xFFFFFFFF; - - /* Save pbuf pointer for push to network layer later */ - lpc_enetdata.rxb[idx] = p; - - /* Wrap at end of descriptor list */ - idx++; - if (idx >= LPC_NUM_BUFF_RXDESCS) { - idx = 0; - } - - /* Queue descriptor(s) */ - lpc_enetdata.rx_free_descs -= 1; - lpc_enetdata.rx_fill_desc_index = idx; - LPC_EMAC->RxConsumeIndex = idx; -} - -/** \brief Attempt to allocate and requeue a new memory buffer for RX - * - * \returns >= 1 if a packet or packets were allocated and requeued, otherwise 0 - */ -int32_t LPC17_EMAC::lpc_rx_queue() -{ - //struct lpc_enetdata *lpc_enetif = netif->state; - emac_mem_buf_t *p; - int32_t queued = 0; - - /* Attempt to requeue as many packets as possible */ - while (lpc_enetdata.rx_free_descs > 0) { - /* Allocate a pbuf from the pool. We need to allocate at the - maximum size as we don't know the size of the yet to be - received packet. */ - p = memory_manager->alloc_heap(EMAC_ETH_MAX_FLEN, 0); - if (p == NULL) { - return queued; - } - - /* Queue packet */ - lpc_rxqueue_pbuf(p); - - /* Update queued count */ - queued++; - } - - return queued; -} - -/** \brief Sets up the RX descriptor ring buffers. - * - * This function sets up the descriptor list used for receive packets. - * - * \returns Always returns ERR_OK - */ -bool LPC17_EMAC::lpc_rx_setup() -{ - /* Setup pointers to RX structures */ - LPC_EMAC->RxDescriptor = (uint32_t) &lpc_enetdata.prxd[0]; - LPC_EMAC->RxStatus = (uint32_t) &lpc_enetdata.prxs[0]; - LPC_EMAC->RxDescriptorNumber = LPC_NUM_BUFF_RXDESCS - 1; - - lpc_enetdata.rx_free_descs = LPC_NUM_BUFF_RXDESCS; - lpc_enetdata.rx_fill_desc_index = 0; - - /* Build RX buffer and descriptors */ - lpc_rx_queue(); - - return true; -} - -/** \brief Allocates a memory buffer and returns the data from the incoming packet. - * - * \return a buffer filled with the received packet (including MAC header) - * NULL on memory error - */ -emac_mem_buf_t *LPC17_EMAC::lpc_low_level_input() -{ - emac_mem_buf_t *p = NULL; - uint32_t idx, length; - uint16_t origLength; - -#ifdef LOCK_RX_THREAD - TXLockMutex.lock(); -#endif - - /* Monitor RX overrun status. This should never happen unless - (possibly) the internal bus is behing held up by something. - Unless your system is running at a very low clock speed or - there are possibilities that the internal buses may be held - up for a long time, this can probably safely be removed. */ - if (LPC_EMAC->IntStatus & EMAC_INT_RX_OVERRUN) { - - /* Temporarily disable RX */ - LPC_EMAC->MAC1 &= ~EMAC_MAC1_REC_EN; - - /* Reset the RX side */ - LPC_EMAC->MAC1 |= EMAC_MAC1_RES_RX; - LPC_EMAC->IntClear = EMAC_INT_RX_OVERRUN; - - /* De-allocate all queued RX pbufs */ - for (idx = 0; idx < LPC_NUM_BUFF_RXDESCS; idx++) { - if (lpc_enetdata.rxb[idx] != NULL) { - memory_manager->free(lpc_enetdata.rxb[idx]); - lpc_enetdata.rxb[idx] = NULL; - } - } - - /* Start RX side again */ - lpc_rx_setup(); - - /* Re-enable RX */ - LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - return NULL; - } - - /* Determine if a frame has been received */ - length = 0; - idx = LPC_EMAC->RxConsumeIndex; - - if (LPC_EMAC->RxProduceIndex != idx) { - /* Handle errors */ - if (lpc_enetdata.prxs[idx].statusinfo & (EMAC_RINFO_CRC_ERR | - EMAC_RINFO_SYM_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_LEN_ERR)) { - - /* Re-queue the buffer for receive */ - lpc_enetdata.rx_free_descs++; - p = lpc_enetdata.rxb[idx]; - lpc_enetdata.rxb[idx] = NULL; - lpc_rxqueue_pbuf(p); - - p = NULL; - } else { - /* A packet is waiting, get length */ - length = (lpc_enetdata.prxs[idx].statusinfo & 0x7FF) + 1; - length -= 4; - - /* Zero-copy */ - p = lpc_enetdata.rxb[idx]; - origLength = memory_manager->get_len(p); - memory_manager->set_len(p, length); - - /* Free buffer from descriptor */ - lpc_enetdata.rxb[idx] = NULL; - lpc_enetdata.rx_free_descs++; - - /* Attempt to queue new buffer(s) */ - if (lpc_rx_queue() == 0) { - /* Re-queue the buffer for receive */ - memory_manager->set_len(p, origLength); - lpc_rxqueue_pbuf(p); - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - return NULL; - } - } - } - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - - return p; -} - -/** \brief Attempt to read a packet from the EMAC interface. - * - */ -void LPC17_EMAC::lpc_enetif_input() -{ - emac_mem_buf_t *p; - - /* move received packet into a new memory buffer */ - p = lpc_low_level_input(); - if (p == NULL) { - return; - } - - emac_link_input_cb(p); -} - -/** \brief Determine if the passed address is usable for the ethernet - * DMA controller. - * - * \param[in] addr Address of packet to check for DMA safe operation - * \return 1 if the packet address is not safe, otherwise 0 - */ -int32_t LPC17_EMAC::lpc_packet_addr_notsafe(void *addr) -{ - /* Check for legal address ranges */ -#if defined(TARGET_LPC17XX) - if ((((uint32_t) addr >= 0x2007C000) && ((uint32_t) addr < 0x20083FFF))) { -#endif - return 0; - } - return 1; -} - -/** \brief Sets up the TX descriptor ring buffers. - * - * This function sets up the descriptor list used for transmit packets. - */ -bool LPC17_EMAC::lpc_tx_setup() -{ - int32_t idx; - - /* Build TX descriptors for local buffers */ - for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { - lpc_enetdata.ptxd[idx].control = 0; - lpc_enetdata.ptxs[idx].statusinfo = 0xFFFFFFFF; - } - - /* Setup pointers to TX structures */ - LPC_EMAC->TxDescriptor = (uint32_t) &lpc_enetdata.ptxd[0]; - LPC_EMAC->TxStatus = (uint32_t) &lpc_enetdata.ptxs[0]; - LPC_EMAC->TxDescriptorNumber = LPC_NUM_BUFF_TXDESCS - 1; - - lpc_enetdata.lpc_last_tx_idx = 0; - lpc_enetdata.lpc_reserved_tx_num = 0; - - return true; -} - -/** \brief Free TX buffers that are complete - * - * \param[in] cidx EMAC current descriptor comsumer index - */ -void LPC17_EMAC::lpc_tx_reclaim_st(uint32_t cidx) -{ - TXLockMutex.lock(); - - // If consume index not last freed index or all descriptors in use - while (cidx != lpc_enetdata.lpc_last_tx_idx || lpc_enetdata.lpc_reserved_tx_num == LPC_NUM_BUFF_TXDESCS) { - if (lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] != NULL) { - memory_manager->free(lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx]); - lpc_enetdata.txb[lpc_enetdata.lpc_last_tx_idx] = NULL; - } - - xTXDCountSem.release(); - - lpc_enetdata.lpc_last_tx_idx++; - if (lpc_enetdata.lpc_last_tx_idx >= LPC_NUM_BUFF_TXDESCS) { - lpc_enetdata.lpc_last_tx_idx = 0; - } - lpc_enetdata.lpc_reserved_tx_num--; - } - - TXLockMutex.unlock(); -} - -/** \brief User call for freeingTX buffers that are complete - * - */ -void LPC17_EMAC::lpc_tx_reclaim() -{ - lpc_tx_reclaim_st(LPC_EMAC->TxConsumeIndex); -} - - /** \brief Polls if an available TX descriptor is ready. Can be used to - * determine if the low level transmit function will block. - * - * \return 0 if no descriptors are read, or >0 - */ -int32_t LPC17_EMAC::lpc_tx_ready() -{ - int32_t fb; - uint32_t idx, cidx; - - cidx = LPC_EMAC->TxConsumeIndex; - idx = LPC_EMAC->TxProduceIndex; - - /* Determine number of free buffers */ - if (idx == cidx) { - fb = LPC_NUM_BUFF_TXDESCS; - } else if (cidx > idx) { - fb = (LPC_NUM_BUFF_TXDESCS - 1) - - ((idx + LPC_NUM_BUFF_TXDESCS) - cidx); - } else { - fb = (LPC_NUM_BUFF_TXDESCS - 1) - (cidx - idx); - } - - return fb; -} - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent - */ -bool LPC17_EMAC::link_out(emac_mem_buf_t *p) -{ - emac_mem_buf_t *q; - uint32_t idx, notdmasafe = 0; - emac_mem_buf_t *np; - int32_t dn; - - /* Zero-copy TX buffers may be fragmented across a memory buffer chain. Determine - the number of descriptors needed for the transfer and make sure packet addresses - are DMA safe. - - A DMA safe address is once that uses external memory or periphheral RAM. - IRAM and FLASH are not safe! */ - dn = 0; - for (q = p; q != NULL; q = memory_manager->get_next(q)) { - ++dn; - void *ptr = memory_manager->get_ptr(q); - notdmasafe += lpc_packet_addr_notsafe(ptr); - } - -#if LPC_TX_PBUF_BOUNCE_EN==1 - /* If the buffer chain is not DMA safe, a new bounce buffer will be - created that will be used instead. This requires an copy from the - non-safe DMA region to the new buffer. */ - if (notdmasafe) { - /* Allocate a buffer in DMA memory. - MEMORY MANAGER HEAP MUST BE IN DMA SAFE MEMORY. */ - np = memory_manager->alloc_heap(memory_manager->get_total_len(p), 0); - if (np == NULL) { - memory_manager->free(p); - return false; - } - memory_manager->copy(np, p); - /* use the new buffer for descriptor queueing. The original buffer will - be de-allocated. */ - memory_manager->free(p); - p = np; - dn = 1; - } -#else - if (notdmasafe) { - MBED_ASSERT(0); - } -#endif - - /* Wait until enough descriptors are available for the transfer. */ - /* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */ - for (int32_t count = 0; count < dn; count++) { - xTXDCountSem.acquire(); - } - - MBED_ASSERT(dn <= lpc_tx_ready()); - - TXLockMutex.lock(); - - /* Get free TX buffer index */ - idx = LPC_EMAC->TxProduceIndex; - - /* Setup transfers */ - q = p; - while (dn > 0) { - dn--; - - /* Only save pointer to free on last descriptor */ - if (dn == 0) { - /* Save size of packet and signal it's ready */ - lpc_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT | - EMAC_TCTRL_LAST; - lpc_enetdata.txb[idx] = p; - } - else { - /* Save size of packet, descriptor is not last */ - lpc_enetdata.ptxd[idx].control = (memory_manager->get_len(q) - 1) | EMAC_TCTRL_INT; - lpc_enetdata.txb[idx] = NULL; - } - - lpc_enetdata.ptxd[idx].packet = (uint32_t) memory_manager->get_ptr(q); - - q = memory_manager->get_next(q); - - idx++; - if (idx >= LPC_NUM_BUFF_TXDESCS) { - idx = 0; - } - lpc_enetdata.lpc_reserved_tx_num++; - } - - LPC_EMAC->TxProduceIndex = idx; - - TXLockMutex.unlock(); - - return true; -} - -/** \brief LPC EMAC interrupt handler. - * - * This function handles the transmit, receive, and error interrupt of - * the LPC177x_8x. This is meant to be used when NO_SYS=0. - */ -void LPC17xxEthernetHandler(void) -{ - LPC17_EMAC &emac = LPC17_EMAC::get_instance(); - - uint32_t ints; - - /* Interrupts are of 2 groups - transmit or receive. Based on the - interrupt, kick off the receive or transmit (cleanup) task */ - - /* Get pending interrupts */ - ints = LPC_EMAC->IntStatus; - - if (ints & RXINTGROUP) { - /* RX group interrupt(s): Give signal to wakeup RX receive task.*/ - osThreadFlagsSet(emac.RxThread, RX_SIGNAL); - } - - if (ints & TXINTGROUP) { - /* TX group interrupt(s): Give semaphore to wakeup TX cleanup task. */ - emac.TxCleanSem.release(); - } - - /* Clear pending interrupts */ - LPC_EMAC->IntClear = ints; -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the IP stacks core. - * - * \param[in] pvParameters Not used yet - */ -void LPC17_EMAC::packet_rx(void* pvParameters) -{ - LPC17_EMAC *lpc17_emac = static_cast(pvParameters); - - while (1) { - /* Wait for receive task to wakeup */ - osThreadFlagsWait(RX_SIGNAL, 0, osWaitForever); - - /* Process packets until all empty */ - while (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { - lpc17_emac->lpc_enetif_input(); - } - } -} - -/** \brief Transmit cleanup task - * - * This task is called when a transmit interrupt occurs and - * reclaims the memory buffer and descriptor used for the packet once - * the packet has been transferred. - * - * \param[in] pvParameters Not used yet - */ -void LPC17_EMAC::packet_tx(void* pvParameters) -{ - LPC17_EMAC *lpc17_emac = static_cast(pvParameters); - int32_t idx; - - while (1) { - /* Wait for transmit cleanup task to wakeup */ - lpc17_emac->TxCleanSem.acquire(); - - /* Error handling for TX underruns. This should never happen unless - something is holding the bus or the clocks are going too slow. It - can probably be safely removed. */ - if (LPC_EMAC->IntStatus & EMAC_INT_TX_UNDERRUN) { - lpc17_emac->TXLockMutex.lock(); - - /* Reset the TX side */ - LPC_EMAC->MAC1 |= EMAC_MAC1_RES_TX; - LPC_EMAC->IntClear = EMAC_INT_TX_UNDERRUN; - - /* De-allocate all queued TX buffers */ - for (idx = 0; idx < LPC_NUM_BUFF_TXDESCS; idx++) { - if (lpc_enetdata.txb[idx] != NULL) { - lpc17_emac->memory_manager->free(lpc_enetdata.txb[idx]); - lpc_enetdata.txb[idx] = NULL; - } - } - - lpc17_emac->TXLockMutex.unlock(); - - /* Start TX side again */ - lpc17_emac->lpc_tx_setup(); - } else { - /* Free TX buffers that are done sending */ - lpc17_emac->lpc_tx_reclaim(); - } - } -} - -/** \brief Low level init of the MAC and PHY. - * - */ -bool LPC17_EMAC::low_level_init() -{ - bool err = true; - - /* Enable MII clocking */ - LPC_SC->PCONP |= CLKPWR_PCONP_PCENET; - -#if defined(TARGET_LPC17XX) - LPC_PINCON->PINSEL2 = 0x50150105; /* Enable P1 Ethernet Pins. */ - LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005; -#endif - - /* Reset all MAC logic */ - LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | - EMAC_MAC1_RES_RX | EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | - EMAC_MAC1_SOFT_RES; - LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | - EMAC_CR_PASS_RUNT_FRM; - osDelay(10); - - /* Initial MAC initialization */ - LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; - LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN | - EMAC_MAC2_VLAN_PAD_EN; - LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; - - /* Set RMII management clock rate to lowest speed */ - LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(11) | EMAC_MCFG_RES_MII; - LPC_EMAC->MCFG &= ~EMAC_MCFG_RES_MII; - - /* Maximum number of retries, 0x37 collision window, gap */ - LPC_EMAC->CLRT = EMAC_CLRT_DEF; - LPC_EMAC->IPGR = EMAC_IPGR_P1_DEF | EMAC_IPGR_P2_DEF; - -#if LPC_EMAC_RMII - /* RMII setup */ - LPC_EMAC->Command = EMAC_CR_PASS_RUNT_FRM | EMAC_CR_RMII; -#else - /* MII setup */ - LPC_EMAC->CR = EMAC_CR_PASS_RUNT_FRM; -#endif - - /* Initialize the PHY and reset */ - err = lpc_phy_init(this, LPC_EMAC_RMII); - if (err == false) { - return false; - } - - /* Save station address */ - LPC_EMAC->SA2 = (uint32_t) hwaddr[0] | - (((uint32_t) hwaddr[1]) << 8); - LPC_EMAC->SA1 = (uint32_t) hwaddr[2] | - (((uint32_t) hwaddr[3]) << 8); - LPC_EMAC->SA0 = (uint32_t) hwaddr[4] | - (((uint32_t) hwaddr[5]) << 8); - - /* Setup transmit and receive descriptors */ - if (lpc_tx_setup() != true) { - return false; - } - if (lpc_rx_setup() != true) { - return false; - } - - /* Enable packet reception */ - LPC_EMAC->RxFilterCtrl = EMAC_RFC_PERFECT_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_MCAST_EN; - - /* Clear and enable rx/tx interrupts */ - LPC_EMAC->IntClear = 0xFFFF; - LPC_EMAC->IntEnable = RXINTGROUP | TXINTGROUP; - - /* Enable RX and TX */ - LPC_EMAC->Command |= EMAC_CR_RX_EN | EMAC_CR_TX_EN; - LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; - - return err; -} - -/* This function provides a method for the PHY to setup the EMAC - for the PHY negotiated duplex mode */ -void lpc_emac_set_duplex(int full_duplex) -{ - if (full_duplex) { - LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; - LPC_EMAC->Command |= EMAC_CR_FULL_DUP; - LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; - } else { - LPC_EMAC->MAC2 &= ~EMAC_MAC2_FULL_DUP; - LPC_EMAC->Command &= ~EMAC_CR_FULL_DUP; - LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; - } -} - -/* This function provides a method for the PHY to setup the EMAC - for the PHY negotiated bit rate */ -void lpc_emac_set_speed(int mbs_100) -{ - if (mbs_100) { - LPC_EMAC->SUPP = EMAC_SUPP_SPEED; - } else { - LPC_EMAC->SUPP = 0; - } -} - -/* periodic PHY status update */ -void LPC17_EMAC::phy_update(void *nif) -{ - LPC17_EMAC *lpc17_emac = static_cast(nif); - - while (true) { - lpc_phy_sts_sm(lpc17_emac); - osDelay(250); - } -} - -void LPC17_EMAC::update_link_status(bool up) -{ - emac_link_state_cb(up); -} - -void LPC17_EMAC::eth_arch_enable_interrupts(void) { - NVIC_SetVector(ENET_IRQn, (uint32_t)LPC17xxEthernetHandler); - NVIC_SetPriority(ENET_IRQn, ((0x01 << 3) | 0x01)); - NVIC_EnableIRQ(ENET_IRQn); -} - -void LPC17_EMAC::eth_arch_disable_interrupts(void) { - NVIC_DisableIRQ(ENET_IRQn); -} - -/** - * Should be called at the beginning of the program to set up the - * network interface. - * - * This function should be passed as a parameter to netif_add(). - * - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -bool LPC17_EMAC::power_up() -{ - bool err = low_level_init(); - if (err != true) { - return false; - } - - RxThread = create_new_thread("lpc17_emac_rx_thread", LPC17_EMAC::packet_rx, this, rx_thread_stack, DEFAULT_THREAD_STACKSIZE, RX_PRIORITY, &RxThread_cb); - TxCleanThread = create_new_thread("lpc17_emac_txclean_thread", LPC17_EMAC::packet_tx, this, tx_clean_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &TxCleanThread_cb); - PhyThread = create_new_thread("lpc17_emac_phy_thread", LPC17_EMAC::phy_update, this, phy_thread_stack, DEFAULT_THREAD_STACKSIZE, TX_PRIORITY, &PhyThread_cb); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - eth_arch_enable_interrupts(); - - return true; -} - -uint32_t LPC17_EMAC::get_mtu_size() const -{ - return 1500; -} - -uint32_t LPC17_EMAC::get_align_preference() const -{ - return 0; -} - -void LPC17_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, LPC17_ETH_IF_NAME, (size < sizeof(LPC17_ETH_IF_NAME)) ? size : sizeof(LPC17_ETH_IF_NAME)); -} - -uint8_t LPC17_EMAC::get_hwaddr_size() const -{ - return LPC17_ETH_HWADDR_SIZE; -} - -bool LPC17_EMAC::get_hwaddr(uint8_t *addr) const -{ - return false; -} - -void LPC17_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, LPC17_ETH_HWADDR_SIZE); - - /* Save station address */ - LPC_EMAC->SA2 = (uint32_t) hwaddr[0] | - (((uint32_t) hwaddr[1]) << 8); - LPC_EMAC->SA1 = (uint32_t) hwaddr[2] | - (((uint32_t) hwaddr[3]) << 8); - LPC_EMAC->SA0 = (uint32_t) hwaddr[4] | - (((uint32_t) hwaddr[5]) << 8); -} - -void LPC17_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void LPC17_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void LPC17_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void LPC17_EMAC::remove_multicast_group(const uint8_t *address) -{ - /* No-op at this stage */ -} - -void LPC17_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void LPC17_EMAC::power_down() -{ - /* No-op at this stage */ -} - -LPC17_EMAC::LPC17_EMAC() - : RxThread(), - RxThread_cb(), - TxCleanSem(), - hwaddr(), - TxCleanThread(), - TxCleanThread_cb(), - PhyThread(), - PhyThread_cb(), - TXLockMutex(), - xTXDCountSem(LPC_NUM_BUFF_TXDESCS), - emac_link_input_cb(0), - emac_link_state_cb(0), - memory_manager(0) -{ -} - -void LPC17_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -LPC17_EMAC &LPC17_EMAC::get_instance() { - static LPC17_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() { - return LPC17_EMAC::get_instance(); -} - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h deleted file mode 100644 index 87ca062..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.h +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef LPC17_EMAC_H_ -#define LPC17_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -#include "lpc_emac_config.h" - -class LPC17_EMAC : public EMAC { -public: - LPC17_EMAC(); - - static LPC17_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - void update_link_status(bool up); - - osThreadId_t RxThread; - mbed_rtos_storage_thread_t RxThread_cb; - rtos::Semaphore TxCleanSem; - -private: - void lpc_rxqueue_pbuf(emac_mem_buf_t *p); - int32_t lpc_rx_queue(); - bool lpc_rx_setup(); - emac_mem_buf_t *lpc_low_level_input(); - void lpc_enetif_input(); - int32_t lpc_packet_addr_notsafe(void *addr); - bool lpc_tx_setup(); - void lpc_tx_reclaim_st(uint32_t cidx); - void lpc_tx_reclaim(); - int32_t lpc_tx_ready(); - static void packet_rx(void* pvParameters); - static void packet_tx(void* pvParameters); - bool low_level_init(); - static void phy_update(void *nif); - bool eth_arch_enetif_init(); - void eth_arch_enable_interrupts(); - void eth_arch_disable_interrupts(); - - uint8_t hwaddr[6]; - - osThreadId_t TxCleanThread; - mbed_rtos_storage_thread_t TxCleanThread_cb; - osThreadId_t PhyThread; - mbed_rtos_storage_thread_t PhyThread_cb; - rtos::Mutex TXLockMutex; - rtos::Semaphore xTXDCountSem; - - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - - EMACMemoryManager *memory_manager; /**< Memory manager */ -}; - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h deleted file mode 100644 index 13019d4..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17xx_emac.h +++ /dev/null @@ -1,665 +0,0 @@ -/********************************************************************** -* $Id$ lpc17xx_emac.h 2010-05-21 -*//** -* @file lpc17xx_emac.h -* @brief Contains all macro definitions and function prototypes -* support for Ethernet MAC firmware library on LPC17xx -* @version 2.0 -* @date 21. May. 2010 -* @author NXP MCU SW Application Team -* -* Copyright(C) 2010, NXP Semiconductor -* All rights reserved. -* -*********************************************************************** -* Software that is described herein is for illustrative purposes only -* which provides customers with programming information regarding the -* products. This software is supplied "AS IS" without any warranties. -* NXP Semiconductors assumes no responsibility or liability for the -* use of the software, conveys no license or title under any patent, -* copyright, or mask work right to the product. NXP Semiconductors -* reserves the right to make changes in the software without -* notification. NXP Semiconductors also make no representation or -* warranty that such application will be suitable for the specified -* use without further testing or modification. -**********************************************************************/ - -/* Peripheral group ----------------------------------------------------------- */ -/** @defgroup EMAC EMAC (Ethernet Media Access Controller) - * @ingroup LPC1700CMSIS_FwLib_Drivers - * @{ - */ - -#ifndef LPC17XX_EMAC_H_ -#define LPC17XX_EMAC_H_ - -/* Includes ------------------------------------------------------------------- */ -#include "cmsis.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define MCB_LPC_1768 -//#define IAR_LPC_1768 - -/* Public Macros -------------------------------------------------------------- */ -/** @defgroup EMAC_Public_Macros EMAC Public Macros - * @{ - */ - - -/* EMAC PHY status type definitions */ -#define EMAC_PHY_STAT_LINK (0) /**< Link Status */ -#define EMAC_PHY_STAT_SPEED (1) /**< Speed Status */ -#define EMAC_PHY_STAT_DUP (2) /**< Duplex Status */ - -/* EMAC PHY device Speed definitions */ -#define EMAC_MODE_AUTO (0) /**< Auto-negotiation mode */ -#define EMAC_MODE_10M_FULL (1) /**< 10Mbps FullDuplex mode */ -#define EMAC_MODE_10M_HALF (2) /**< 10Mbps HalfDuplex mode */ -#define EMAC_MODE_100M_FULL (3) /**< 100Mbps FullDuplex mode */ -#define EMAC_MODE_100M_HALF (4) /**< 100Mbps HalfDuplex mode */ - -/** - * @} - */ -/* Private Macros ------------------------------------------------------------- */ -/** @defgroup EMAC_Private_Macros EMAC Private Macros - * @{ - */ - - -/* EMAC Memory Buffer configuration for 16K Ethernet RAM */ -#define EMAC_NUM_RX_FRAG 4 /**< Num.of RX Fragments 4*1536= 6.0kB */ -#define EMAC_NUM_TX_FRAG 3 /**< Num.of TX Fragments 3*1536= 4.6kB */ -#define EMAC_ETH_MAX_FLEN 1536 /**< Max. Ethernet Frame Size */ -#define EMAC_TX_FRAME_TOUT 0x00100000 /**< Frame Transmit timeout count */ - -/* --------------------- BIT DEFINITIONS -------------------------------------- */ -/*********************************************************************//** - * Macro defines for MAC Configuration Register 1 - **********************************************************************/ -#define EMAC_MAC1_REC_EN 0x00000001 /**< Receive Enable */ -#define EMAC_MAC1_PASS_ALL 0x00000002 /**< Pass All Receive Frames */ -#define EMAC_MAC1_RX_FLOWC 0x00000004 /**< RX Flow Control */ -#define EMAC_MAC1_TX_FLOWC 0x00000008 /**< TX Flow Control */ -#define EMAC_MAC1_LOOPB 0x00000010 /**< Loop Back Mode */ -#define EMAC_MAC1_RES_TX 0x00000100 /**< Reset TX Logic */ -#define EMAC_MAC1_RES_MCS_TX 0x00000200 /**< Reset MAC TX Control Sublayer */ -#define EMAC_MAC1_RES_RX 0x00000400 /**< Reset RX Logic */ -#define EMAC_MAC1_RES_MCS_RX 0x00000800 /**< Reset MAC RX Control Sublayer */ -#define EMAC_MAC1_SIM_RES 0x00004000 /**< Simulation Reset */ -#define EMAC_MAC1_SOFT_RES 0x00008000 /**< Soft Reset MAC */ - -/*********************************************************************//** - * Macro defines for MAC Configuration Register 2 - **********************************************************************/ -#define EMAC_MAC2_FULL_DUP 0x00000001 /**< Full-Duplex Mode */ -#define EMAC_MAC2_FRM_LEN_CHK 0x00000002 /**< Frame Length Checking */ -#define EMAC_MAC2_HUGE_FRM_EN 0x00000004 /**< Huge Frame Enable */ -#define EMAC_MAC2_DLY_CRC 0x00000008 /**< Delayed CRC Mode */ -#define EMAC_MAC2_CRC_EN 0x00000010 /**< Append CRC to every Frame */ -#define EMAC_MAC2_PAD_EN 0x00000020 /**< Pad all Short Frames */ -#define EMAC_MAC2_VLAN_PAD_EN 0x00000040 /**< VLAN Pad Enable */ -#define EMAC_MAC2_ADET_PAD_EN 0x00000080 /**< Auto Detect Pad Enable */ -#define EMAC_MAC2_PPREAM_ENF 0x00000100 /**< Pure Preamble Enforcement */ -#define EMAC_MAC2_LPREAM_ENF 0x00000200 /**< Long Preamble Enforcement */ -#define EMAC_MAC2_NO_BACKOFF 0x00001000 /**< No Backoff Algorithm */ -#define EMAC_MAC2_BACK_PRESSURE 0x00002000 /**< Backoff Presurre / No Backoff */ -#define EMAC_MAC2_EXCESS_DEF 0x00004000 /**< Excess Defer */ - -/*********************************************************************//** - * Macro defines for Back-to-Back Inter-Packet-Gap Register - **********************************************************************/ -/** Programmable field representing the nibble time offset of the minimum possible period - * between the end of any transmitted packet to the beginning of the next */ -#define EMAC_IPGT_BBIPG(n) (n&0x7F) -/** Recommended value for Full Duplex of Programmable field representing the nibble time - * offset of the minimum possible period between the end of any transmitted packet to the - * beginning of the next */ -#define EMAC_IPGT_FULL_DUP (EMAC_IPGT_BBIPG(0x15)) -/** Recommended value for Half Duplex of Programmable field representing the nibble time - * offset of the minimum possible period between the end of any transmitted packet to the - * beginning of the next */ -#define EMAC_IPGT_HALF_DUP (EMAC_IPGT_BBIPG(0x12)) - -/*********************************************************************//** - * Macro defines for Non Back-to-Back Inter-Packet-Gap Register - **********************************************************************/ -/** Programmable field representing the Non-Back-to-Back Inter-Packet-Gap */ -#define EMAC_IPGR_NBBIPG_P2(n) (n&0x7F) -/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 1 */ -#define EMAC_IPGR_P2_DEF (EMAC_IPGR_NBBIPG_P2(0x12)) -/** Programmable field representing the optional carrierSense window referenced in - * IEEE 802.3/4.2.3.2.1 'Carrier Deference' */ -#define EMAC_IPGR_NBBIPG_P1(n) ((n&0x7F)<<8) -/** Recommended value for Programmable field representing the Non-Back-to-Back Inter-Packet-Gap Part 2 */ -#define EMAC_IPGR_P1_DEF EMAC_IPGR_NBBIPG_P1(0x0C) - -/*********************************************************************//** - * Macro defines for Collision Window/Retry Register - **********************************************************************/ -/** Programmable field specifying the number of retransmission attempts following a collision before - * aborting the packet due to excessive collisions */ -#define EMAC_CLRT_MAX_RETX(n) (n&0x0F) -/** Programmable field representing the slot time or collision window during which collisions occur - * in properly configured networks */ -#define EMAC_CLRT_COLL(n) ((n&0x3F)<<8) -/** Default value for Collision Window / Retry register */ -#define EMAC_CLRT_DEF ((EMAC_CLRT_MAX_RETX(0x0F))|(EMAC_CLRT_COLL(0x37))) - -/*********************************************************************//** - * Macro defines for Maximum Frame Register - **********************************************************************/ -/** Represents a maximum receive frame of 1536 octets */ -#define EMAC_MAXF_MAXFRMLEN(n) (n&0xFFFF) - -/*********************************************************************//** - * Macro defines for PHY Support Register - **********************************************************************/ -#define EMAC_SUPP_SPEED 0x00000100 /**< Reduced MII Logic Current Speed */ -#define EMAC_SUPP_RES_RMII 0x00000800 /**< Reset Reduced MII Logic */ - -/*********************************************************************//** - * Macro defines for Test Register - **********************************************************************/ -#define EMAC_TEST_SHCUT_PQUANTA 0x00000001 /**< Shortcut Pause Quanta */ -#define EMAC_TEST_TST_PAUSE 0x00000002 /**< Test Pause */ -#define EMAC_TEST_TST_BACKP 0x00000004 /**< Test Back Pressure */ - -/*********************************************************************//** - * Macro defines for MII Management Configuration Register - **********************************************************************/ -#define EMAC_MCFG_SCAN_INC 0x00000001 /**< Scan Increment PHY Address */ -#define EMAC_MCFG_SUPP_PREAM 0x00000002 /**< Suppress Preamble */ -#define EMAC_MCFG_CLK_SEL(n) ((n&0x0F)<<2) /**< Clock Select Field */ -#define EMAC_MCFG_RES_MII 0x00008000 /**< Reset MII Management Hardware */ -#define EMAC_MCFG_MII_MAXCLK 2500000UL /**< MII Clock max */ - -/*********************************************************************//** - * Macro defines for MII Management Command Register - **********************************************************************/ -#define EMAC_MCMD_READ 0x00000001 /**< MII Read */ -#define EMAC_MCMD_SCAN 0x00000002 /**< MII Scan continuously */ - -#define EMAC_MII_WR_TOUT 0x00050000 /**< MII Write timeout count */ -#define EMAC_MII_RD_TOUT 0x00050000 /**< MII Read timeout count */ - -/*********************************************************************//** - * Macro defines for MII Management Address Register - **********************************************************************/ -#define EMAC_MADR_REG_ADR(n) (n&0x1F) /**< MII Register Address field */ -#define EMAC_MADR_PHY_ADR(n) ((n&0x1F)<<8) /**< PHY Address Field */ - -/*********************************************************************//** - * Macro defines for MII Management Write Data Register - **********************************************************************/ -#define EMAC_MWTD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Write Data register */ - -/*********************************************************************//** - * Macro defines for MII Management Read Data Register - **********************************************************************/ -#define EMAC_MRDD_DATA(n) (n&0xFFFF) /**< Data field for MMI Management Read Data register */ - -/*********************************************************************//** - * Macro defines for MII Management Indicators Register - **********************************************************************/ -#define EMAC_MIND_BUSY 0x00000001 /**< MII is Busy */ -#define EMAC_MIND_SCAN 0x00000002 /**< MII Scanning in Progress */ -#define EMAC_MIND_NOT_VAL 0x00000004 /**< MII Read Data not valid */ -#define EMAC_MIND_MII_LINK_FAIL 0x00000008 /**< MII Link Failed */ - -/* Station Address 0 Register */ -/* Station Address 1 Register */ -/* Station Address 2 Register */ - - -/* Control register definitions --------------------------------------------------------------------------- */ -/*********************************************************************//** - * Macro defines for Command Register - **********************************************************************/ -#define EMAC_CR_RX_EN 0x00000001 /**< Enable Receive */ -#define EMAC_CR_TX_EN 0x00000002 /**< Enable Transmit */ -#define EMAC_CR_REG_RES 0x00000008 /**< Reset Host Registers */ -#define EMAC_CR_TX_RES 0x00000010 /**< Reset Transmit Datapath */ -#define EMAC_CR_RX_RES 0x00000020 /**< Reset Receive Datapath */ -#define EMAC_CR_PASS_RUNT_FRM 0x00000040 /**< Pass Runt Frames */ -#define EMAC_CR_PASS_RX_FILT 0x00000080 /**< Pass RX Filter */ -#define EMAC_CR_TX_FLOW_CTRL 0x00000100 /**< TX Flow Control */ -#define EMAC_CR_RMII 0x00000200 /**< Reduced MII Interface */ -#define EMAC_CR_FULL_DUP 0x00000400 /**< Full Duplex */ - -/*********************************************************************//** - * Macro defines for Status Register - **********************************************************************/ -#define EMAC_SR_RX_EN 0x00000001 /**< Enable Receive */ -#define EMAC_SR_TX_EN 0x00000002 /**< Enable Transmit */ - -/*********************************************************************//** - * Macro defines for Transmit Status Vector 0 Register - **********************************************************************/ -#define EMAC_TSV0_CRC_ERR 0x00000001 /**< CRC error */ -#define EMAC_TSV0_LEN_CHKERR 0x00000002 /**< Length Check Error */ -#define EMAC_TSV0_LEN_OUTRNG 0x00000004 /**< Length Out of Range */ -#define EMAC_TSV0_DONE 0x00000008 /**< Tramsmission Completed */ -#define EMAC_TSV0_MCAST 0x00000010 /**< Multicast Destination */ -#define EMAC_TSV0_BCAST 0x00000020 /**< Broadcast Destination */ -#define EMAC_TSV0_PKT_DEFER 0x00000040 /**< Packet Deferred */ -#define EMAC_TSV0_EXC_DEFER 0x00000080 /**< Excessive Packet Deferral */ -#define EMAC_TSV0_EXC_COLL 0x00000100 /**< Excessive Collision */ -#define EMAC_TSV0_LATE_COLL 0x00000200 /**< Late Collision Occured */ -#define EMAC_TSV0_GIANT 0x00000400 /**< Giant Frame */ -#define EMAC_TSV0_UNDERRUN 0x00000800 /**< Buffer Underrun */ -#define EMAC_TSV0_BYTES 0x0FFFF000 /**< Total Bytes Transferred */ -#define EMAC_TSV0_CTRL_FRAME 0x10000000 /**< Control Frame */ -#define EMAC_TSV0_PAUSE 0x20000000 /**< Pause Frame */ -#define EMAC_TSV0_BACK_PRESS 0x40000000 /**< Backpressure Method Applied */ -#define EMAC_TSV0_VLAN 0x80000000 /**< VLAN Frame */ - -/*********************************************************************//** - * Macro defines for Transmit Status Vector 1 Register - **********************************************************************/ -#define EMAC_TSV1_BYTE_CNT 0x0000FFFF /**< Transmit Byte Count */ -#define EMAC_TSV1_COLL_CNT 0x000F0000 /**< Transmit Collision Count */ - -/*********************************************************************//** - * Macro defines for Receive Status Vector Register - **********************************************************************/ -#define EMAC_RSV_BYTE_CNT 0x0000FFFF /**< Receive Byte Count */ -#define EMAC_RSV_PKT_IGNORED 0x00010000 /**< Packet Previously Ignored */ -#define EMAC_RSV_RXDV_SEEN 0x00020000 /**< RXDV Event Previously Seen */ -#define EMAC_RSV_CARR_SEEN 0x00040000 /**< Carrier Event Previously Seen */ -#define EMAC_RSV_REC_CODEV 0x00080000 /**< Receive Code Violation */ -#define EMAC_RSV_CRC_ERR 0x00100000 /**< CRC Error */ -#define EMAC_RSV_LEN_CHKERR 0x00200000 /**< Length Check Error */ -#define EMAC_RSV_LEN_OUTRNG 0x00400000 /**< Length Out of Range */ -#define EMAC_RSV_REC_OK 0x00800000 /**< Frame Received OK */ -#define EMAC_RSV_MCAST 0x01000000 /**< Multicast Frame */ -#define EMAC_RSV_BCAST 0x02000000 /**< Broadcast Frame */ -#define EMAC_RSV_DRIB_NIBB 0x04000000 /**< Dribble Nibble */ -#define EMAC_RSV_CTRL_FRAME 0x08000000 /**< Control Frame */ -#define EMAC_RSV_PAUSE 0x10000000 /**< Pause Frame */ -#define EMAC_RSV_UNSUPP_OPC 0x20000000 /**< Unsupported Opcode */ -#define EMAC_RSV_VLAN 0x40000000 /**< VLAN Frame */ - -/*********************************************************************//** - * Macro defines for Flow Control Counter Register - **********************************************************************/ -#define EMAC_FCC_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter */ -#define EMAC_FCC_PAUSE_TIM(n) ((n&0xFFFF)<<16) /**< Pause Timer */ - -/*********************************************************************//** - * Macro defines for Flow Control Status Register - **********************************************************************/ -#define EMAC_FCS_MIRR_CNT(n) (n&0xFFFF) /**< Mirror Counter Current */ - - -/* Receive filter register definitions -------------------------------------------------------- */ -/*********************************************************************//** - * Macro defines for Receive Filter Control Register - **********************************************************************/ -#define EMAC_RFC_UCAST_EN 0x00000001 /**< Accept Unicast Frames Enable */ -#define EMAC_RFC_BCAST_EN 0x00000002 /**< Accept Broadcast Frames Enable */ -#define EMAC_RFC_MCAST_EN 0x00000004 /**< Accept Multicast Frames Enable */ -#define EMAC_RFC_UCAST_HASH_EN 0x00000008 /**< Accept Unicast Hash Filter Frames */ -#define EMAC_RFC_MCAST_HASH_EN 0x00000010 /**< Accept Multicast Hash Filter Fram.*/ -#define EMAC_RFC_PERFECT_EN 0x00000020 /**< Accept Perfect Match Enable */ -#define EMAC_RFC_MAGP_WOL_EN 0x00001000 /**< Magic Packet Filter WoL Enable */ -#define EMAC_RFC_PFILT_WOL_EN 0x00002000 /**< Perfect Filter WoL Enable */ - -/*********************************************************************//** - * Macro defines for Receive Filter WoL Status/Clear Registers - **********************************************************************/ -#define EMAC_WOL_UCAST 0x00000001 /**< Unicast Frame caused WoL */ -#define EMAC_WOL_BCAST 0x00000002 /**< Broadcast Frame caused WoL */ -#define EMAC_WOL_MCAST 0x00000004 /**< Multicast Frame caused WoL */ -#define EMAC_WOL_UCAST_HASH 0x00000008 /**< Unicast Hash Filter Frame WoL */ -#define EMAC_WOL_MCAST_HASH 0x00000010 /**< Multicast Hash Filter Frame WoL */ -#define EMAC_WOL_PERFECT 0x00000020 /**< Perfect Filter WoL */ -#define EMAC_WOL_RX_FILTER 0x00000080 /**< RX Filter caused WoL */ -#define EMAC_WOL_MAG_PACKET 0x00000100 /**< Magic Packet Filter caused WoL */ -#define EMAC_WOL_BITMASK 0x01BF /**< Receive Filter WoL Status/Clear bitmasl value */ - - -/* Module control register definitions ---------------------------------------------------- */ -/*********************************************************************//** - * Macro defines for Interrupt Status/Enable/Clear/Set Registers - **********************************************************************/ -#define EMAC_INT_RX_OVERRUN 0x00000001 /**< Overrun Error in RX Queue */ -#define EMAC_INT_RX_ERR 0x00000002 /**< Receive Error */ -#define EMAC_INT_RX_FIN 0x00000004 /**< RX Finished Process Descriptors */ -#define EMAC_INT_RX_DONE 0x00000008 /**< Receive Done */ -#define EMAC_INT_TX_UNDERRUN 0x00000010 /**< Transmit Underrun */ -#define EMAC_INT_TX_ERR 0x00000020 /**< Transmit Error */ -#define EMAC_INT_TX_FIN 0x00000040 /**< TX Finished Process Descriptors */ -#define EMAC_INT_TX_DONE 0x00000080 /**< Transmit Done */ -#define EMAC_INT_SOFT_INT 0x00001000 /**< Software Triggered Interrupt */ -#define EMAC_INT_WAKEUP 0x00002000 /**< Wakeup Event Interrupt */ - -/*********************************************************************//** - * Macro defines for Power Down Register - **********************************************************************/ -#define EMAC_PD_POWER_DOWN 0x80000000 /**< Power Down MAC */ - -/* Descriptor and status formats ---------------------------------------------------- */ -/*********************************************************************//** - * Macro defines for RX Descriptor Control Word - **********************************************************************/ -#define EMAC_RCTRL_SIZE(n) (n&0x7FF) /**< Buffer size field */ -#define EMAC_RCTRL_INT 0x80000000 /**< Generate RxDone Interrupt */ - -/*********************************************************************//** - * Macro defines for RX Status Hash CRC Word - **********************************************************************/ -#define EMAC_RHASH_SA 0x000001FF /**< Hash CRC for Source Address */ -#define EMAC_RHASH_DA 0x001FF000 /**< Hash CRC for Destination Address */ - -/*********************************************************************//** - * Macro defines for RX Status Information Word - **********************************************************************/ -#define EMAC_RINFO_SIZE 0x000007FF /**< Data size in bytes */ -#define EMAC_RINFO_CTRL_FRAME 0x00040000 /**< Control Frame */ -#define EMAC_RINFO_VLAN 0x00080000 /**< VLAN Frame */ -#define EMAC_RINFO_FAIL_FILT 0x00100000 /**< RX Filter Failed */ -#define EMAC_RINFO_MCAST 0x00200000 /**< Multicast Frame */ -#define EMAC_RINFO_BCAST 0x00400000 /**< Broadcast Frame */ -#define EMAC_RINFO_CRC_ERR 0x00800000 /**< CRC Error in Frame */ -#define EMAC_RINFO_SYM_ERR 0x01000000 /**< Symbol Error from PHY */ -#define EMAC_RINFO_LEN_ERR 0x02000000 /**< Length Error */ -#define EMAC_RINFO_RANGE_ERR 0x04000000 /**< Range Error (exceeded max. size) */ -#define EMAC_RINFO_ALIGN_ERR 0x08000000 /**< Alignment Error */ -#define EMAC_RINFO_OVERRUN 0x10000000 /**< Receive overrun */ -#define EMAC_RINFO_NO_DESCR 0x20000000 /**< No new Descriptor available */ -#define EMAC_RINFO_LAST_FLAG 0x40000000 /**< Last Fragment in Frame */ -#define EMAC_RINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */ -#define EMAC_RINFO_ERR_MASK (EMAC_RINFO_FAIL_FILT | EMAC_RINFO_CRC_ERR | EMAC_RINFO_SYM_ERR | \ -EMAC_RINFO_LEN_ERR | EMAC_RINFO_ALIGN_ERR | EMAC_RINFO_OVERRUN) - -/*********************************************************************//** - * Macro defines for TX Descriptor Control Word - **********************************************************************/ -#define EMAC_TCTRL_SIZE 0x000007FF /**< Size of data buffer in bytes */ -#define EMAC_TCTRL_OVERRIDE 0x04000000 /**< Override Default MAC Registers */ -#define EMAC_TCTRL_HUGE 0x08000000 /**< Enable Huge Frame */ -#define EMAC_TCTRL_PAD 0x10000000 /**< Pad short Frames to 64 bytes */ -#define EMAC_TCTRL_CRC 0x20000000 /**< Append a hardware CRC to Frame */ -#define EMAC_TCTRL_LAST 0x40000000 /**< Last Descriptor for TX Frame */ -#define EMAC_TCTRL_INT 0x80000000 /**< Generate TxDone Interrupt */ - -/*********************************************************************//** - * Macro defines for TX Status Information Word - **********************************************************************/ -#define EMAC_TINFO_COL_CNT 0x01E00000 /**< Collision Count */ -#define EMAC_TINFO_DEFER 0x02000000 /**< Packet Deferred (not an error) */ -#define EMAC_TINFO_EXCESS_DEF 0x04000000 /**< Excessive Deferral */ -#define EMAC_TINFO_EXCESS_COL 0x08000000 /**< Excessive Collision */ -#define EMAC_TINFO_LATE_COL 0x10000000 /**< Late Collision Occured */ -#define EMAC_TINFO_UNDERRUN 0x20000000 /**< Transmit Underrun */ -#define EMAC_TINFO_NO_DESCR 0x40000000 /**< No new Descriptor available */ -#define EMAC_TINFO_ERR 0x80000000 /**< Error Occured (OR of all errors) */ - -#ifdef MCB_LPC_1768 -/* DP83848C PHY definition ------------------------------------------------------------ */ - -/** PHY device reset time out definition */ -#define EMAC_PHY_RESP_TOUT 0x100000UL - -/* ENET Device Revision ID */ -#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */ - -/*********************************************************************//** - * Macro defines for DP83848C PHY Registers - **********************************************************************/ -#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */ -#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */ -#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */ -#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */ -#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */ -#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */ -#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */ -#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */ -#define EMAC_PHY_REG_LPNPA 0x08 - -/*********************************************************************//** - * Macro defines for PHY Extended Registers - **********************************************************************/ -#define EMAC_PHY_REG_STS 0x10 /**< Status Register */ -#define EMAC_PHY_REG_MICR 0x11 /**< MII Interrupt Control Register */ -#define EMAC_PHY_REG_MISR 0x12 /**< MII Interrupt Status Register */ -#define EMAC_PHY_REG_FCSCR 0x14 /**< False Carrier Sense Counter */ -#define EMAC_PHY_REG_RECR 0x15 /**< Receive Error Counter */ -#define EMAC_PHY_REG_PCSR 0x16 /**< PCS Sublayer Config. and Status */ -#define EMAC_PHY_REG_RBR 0x17 /**< RMII and Bypass Register */ -#define EMAC_PHY_REG_LEDCR 0x18 /**< LED Direct Control Register */ -#define EMAC_PHY_REG_PHYCR 0x19 /**< PHY Control Register */ -#define EMAC_PHY_REG_10BTSCR 0x1A /**< 10Base-T Status/Control Register */ -#define EMAC_PHY_REG_CDCTRL1 0x1B /**< CD Test Control and BIST Extens. */ -#define EMAC_PHY_REG_EDCR 0x1D /**< Energy Detect Control Register */ - -/*********************************************************************//** - * Macro defines for PHY Basic Mode Control Register - **********************************************************************/ -#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */ -#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */ -#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */ -#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */ -#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */ -#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */ -#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */ -#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */ - -/*********************************************************************//** - * Macro defines for PHY Basic Mode Status Status Register - **********************************************************************/ -#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */ -#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */ -#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */ -#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */ -#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */ -#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */ -#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */ -#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */ -#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */ -#define EMAC_PHY_BMSR_LINK_ESTABLISHED (1<<2) /**< Link status */ - -/*********************************************************************//** - * Macro defines for PHY Status Register - **********************************************************************/ -#define EMAC_PHY_SR_REMOTE_FAULT (1<<6) /**< Remote Fault */ -#define EMAC_PHY_SR_JABBER (1<<5) /**< Jabber detect */ -#define EMAC_PHY_SR_AUTO_DONE (1<<4) /**< Auto Negotiation complete */ -#define EMAC_PHY_SR_LOOPBACK (1<<3) /**< Loop back status */ -#define EMAC_PHY_SR_DUP (1<<2) /**< Duplex status */ -#define EMAC_PHY_SR_SPEED (1<<1) /**< Speed status */ -#define EMAC_PHY_SR_LINK (1<<0) /**< Link Status */ - -#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */ -#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */ -#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */ -#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */ -#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */ - -#define EMAC_DEF_ADR 0x0100 /**< Default PHY device address */ -#define EMAC_DP83848C_ID 0x20005C90 /**< PHY Identifier */ - -#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13)) -#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12)) -#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */ - -#elif defined(IAR_LPC_1768) -/* KSZ8721BL PHY definition ------------------------------------------------------------ */ -/** PHY device reset time out definition */ -#define EMAC_PHY_RESP_TOUT 0x100000UL - -/* ENET Device Revision ID */ -#define EMAC_OLD_EMAC_MODULE_ID 0x39022000 /**< Rev. ID for first rev '-' */ - -/*********************************************************************//** - * Macro defines for KSZ8721BL PHY Registers - **********************************************************************/ -#define EMAC_PHY_REG_BMCR 0x00 /**< Basic Mode Control Register */ -#define EMAC_PHY_REG_BMSR 0x01 /**< Basic Mode Status Register */ -#define EMAC_PHY_REG_IDR1 0x02 /**< PHY Identifier 1 */ -#define EMAC_PHY_REG_IDR2 0x03 /**< PHY Identifier 2 */ -#define EMAC_PHY_REG_ANAR 0x04 /**< Auto-Negotiation Advertisement */ -#define EMAC_PHY_REG_ANLPAR 0x05 /**< Auto-Neg. Link Partner Abitily */ -#define EMAC_PHY_REG_ANER 0x06 /**< Auto-Neg. Expansion Register */ -#define EMAC_PHY_REG_ANNPTR 0x07 /**< Auto-Neg. Next Page TX */ -#define EMAC_PHY_REG_LPNPA 0x08 /**< Link Partner Next Page Ability */ -#define EMAC_PHY_REG_REC 0x15 /**< RXError Counter Register */ -#define EMAC_PHY_REG_ISC 0x1b /**< Interrupt Control/Status Register */ -#define EMAC_PHY_REG_100BASE 0x1f /**< 100BASE-TX PHY Control Register */ - -/*********************************************************************//** - * Macro defines for PHY Basic Mode Control Register - **********************************************************************/ -#define EMAC_PHY_BMCR_RESET (1<<15) /**< Reset bit */ -#define EMAC_PHY_BMCR_LOOPBACK (1<<14) /**< Loop back */ -#define EMAC_PHY_BMCR_SPEED_SEL (1<<13) /**< Speed selection */ -#define EMAC_PHY_BMCR_AN (1<<12) /**< Auto Negotiation */ -#define EMAC_PHY_BMCR_POWERDOWN (1<<11) /**< Power down mode */ -#define EMAC_PHY_BMCR_ISOLATE (1<<10) /**< Isolate */ -#define EMAC_PHY_BMCR_RE_AN (1<<9) /**< Restart auto negotiation */ -#define EMAC_PHY_BMCR_DUPLEX (1<<8) /**< Duplex mode */ -#define EMAC_PHY_BMCR_COLLISION (1<<7) /**< Collision test */ -#define EMAC_PHY_BMCR_TXDIS (1<<0) /**< Disable transmit */ - -/*********************************************************************//** - * Macro defines for PHY Basic Mode Status Register - **********************************************************************/ -#define EMAC_PHY_BMSR_100BE_T4 (1<<15) /**< 100 base T4 */ -#define EMAC_PHY_BMSR_100TX_FULL (1<<14) /**< 100 base full duplex */ -#define EMAC_PHY_BMSR_100TX_HALF (1<<13) /**< 100 base half duplex */ -#define EMAC_PHY_BMSR_10BE_FULL (1<<12) /**< 10 base T full duplex */ -#define EMAC_PHY_BMSR_10BE_HALF (1<<11) /**< 10 base T half duplex */ -#define EMAC_PHY_BMSR_NOPREAM (1<<6) /**< MF Preamable Supress */ -#define EMAC_PHY_BMSR_AUTO_DONE (1<<5) /**< Auto negotiation complete */ -#define EMAC_PHY_BMSR_REMOTE_FAULT (1<<4) /**< Remote fault */ -#define EMAC_PHY_BMSR_NO_AUTO (1<<3) /**< Auto Negotiation ability */ -#define EMAC_PHY_BMSR_LINK_STATUS (1<<2) /**< Link status */ -#define EMAC_PHY_BMSR_JABBER_DETECT (1<<1) /**< Jabber detect */ -#define EMAC_PHY_BMSR_EXTEND (1<<0) /**< Extended support */ - -/*********************************************************************//** - * Macro defines for PHY Identifier - **********************************************************************/ -/* PHY Identifier 1 bitmap definitions */ -#define EMAC_PHY_IDR1(n) (n & 0xFFFF) /**< PHY ID1 Number */ - -/* PHY Identifier 2 bitmap definitions */ -#define EMAC_PHY_IDR2(n) (n & 0xFFFF) /**< PHY ID2 Number */ - -/*********************************************************************//** - * Macro defines for Auto-Negotiation Advertisement - **********************************************************************/ -#define EMAC_PHY_AN_NEXTPAGE (1<<15) /**< Next page capable */ -#define EMAC_PHY_AN_REMOTE_FAULT (1<<13) /**< Remote Fault support */ -#define EMAC_PHY_AN_PAUSE (1<<10) /**< Pause support */ -#define EMAC_PHY_AN_100BASE_T4 (1<<9) /**< T4 capable */ -#define EMAC_PHY_AN_100BASE_TX_FD (1<<8) /**< TX with Full-duplex capable */ -#define EMAC_PHY_AN_100BASE_TX (1<<7) /**< TX capable */ -#define EMAC_PHY_AN_10BASE_T_FD (1<<6) /**< 10Mbps with full-duplex capable */ -#define EMAC_PHY_AN_10BASE_T (1<<5) /**< 10Mbps capable */ -#define EMAC_PHY_AN_FIELD(n) (n & 0x1F) /**< Selector Field */ - -#define EMAC_PHY_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */ -#define EMAC_PHY_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */ -#define EMAC_PHY_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */ -#define EMAC_PHY_HALFD_10M 0x0000 /**< Half Duplex 10MBit */ -#define EMAC_PHY_AUTO_NEG 0x3000 /**< Select Auto Negotiation */ - -#define EMAC_PHY_SR_100_SPEED ((1<<14)|(1<<13)) -#define EMAC_PHY_SR_FULL_DUP ((1<<14)|(1<<12)) - -#define EMAC_DEF_ADR (0x01<<8) /**< Default PHY device address */ -#define EMAC_KSZ8721BL_ID ((0x22 << 16) | 0x1619 ) /**< PHY Identifier */ -#endif - -/** - * @} - */ - - -/* Public Types --------------------------------------------------------------- */ -/** @defgroup EMAC_Public_Types EMAC Public Types - * @{ - */ - -/* Descriptor and status formats ---------------------------------------------- */ - -/** - * @brief RX Descriptor structure type definition - */ -typedef struct { - uint32_t Packet; /**< Receive Packet Descriptor */ - uint32_t Ctrl; /**< Receive Control Descriptor */ -} RX_Desc; - -/** - * @brief RX Status structure type definition - */ -typedef struct { - uint32_t Info; /**< Receive Information Status */ - uint32_t HashCRC; /**< Receive Hash CRC Status */ -} RX_Stat; - -/** - * @brief TX Descriptor structure type definition - */ -typedef struct { - uint32_t Packet; /**< Transmit Packet Descriptor */ - uint32_t Ctrl; /**< Transmit Control Descriptor */ -} TX_Desc; - -/** - * @brief TX Status structure type definition - */ -typedef struct { - uint32_t Info; /**< Transmit Information Status */ -} TX_Stat; - - -/** - * @brief TX Data Buffer structure definition - */ -typedef struct { - uint32_t ulDataLen; /**< Data length */ - uint32_t *pbDataBuf; /**< A word-align data pointer to data buffer */ -} EMAC_PACKETBUF_Type; - -/** - * @brief EMAC configuration structure definition - */ -typedef struct { - uint32_t Mode; /**< Supported EMAC PHY device speed, should be one of the following: - - EMAC_MODE_AUTO - - EMAC_MODE_10M_FULL - - EMAC_MODE_10M_HALF - - EMAC_MODE_100M_FULL - - EMAC_MODE_100M_HALF - */ - uint8_t *pbEMAC_Addr; /**< Pointer to EMAC Station address that contains 6-bytes - of MAC address, it must be sorted in order (bEMAC_Addr[0]..[5]) - */ -} EMAC_CFG_Type; - -/** Ethernet block power/clock control bit*/ -#define CLKPWR_PCONP_PCENET ((uint32_t)(1<<30)) - -#ifdef __cplusplus -} -#endif - -#endif /* LPC17XX_EMAC_H_ */ - -/** - * @} - */ - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h deleted file mode 100644 index 43efb8a..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_emac_config.h +++ /dev/null @@ -1,104 +0,0 @@ -/********************************************************************** -* $Id$ lpc_emac_config.h 2011-11-20 -*//** -* @file lpc_emac_config.h -* @brief PHY and EMAC configuration file -* @version 1.0 -* @date 20 Nov. 2011 -* @author NXP MCU SW Application Team -* -* Copyright(C) 2011, NXP Semiconductor -* All rights reserved. -* -*********************************************************************** -* Software that is described herein is for illustrative purposes only -* which provides customers with programming information regarding the -* products. This software is supplied "AS IS" without any warranties. -* NXP Semiconductors assumes no responsibility or liability for the -* use of the software, conveys no license or title under any patent, -* copyright, or mask work right to the product. NXP Semiconductors -* reserves the right to make changes in the software without -* notification. NXP Semiconductors also make no representation or -* warranty that such application will be suitable for the specified -* use without further testing or modification. -**********************************************************************/ - -#ifndef __LPC_EMAC_CONFIG_H -#define __LPC_EMAC_CONFIG_H - -#define LPC17_ETH_IF_NAME "lpc" -#define LPC17_ETH_HWADDR_SIZE 6 - -#define DEFAULT_THREAD_STACKSIZE 512 - -/** @defgroup lwip_phy_config PHY configuration - * @ingroup lwip_phy - * - * Configuration options for the PHY connected to the LPC EMAC. - * @{ - */ - -/** \brief The PHY address connected the to MII/RMII - */ -#define LPC_PHYDEF_PHYADDR 1 /**< The PHY address on the PHY device. */ - -/** \brief Enable autonegotiation mode. - * If this is enabled, the PHY will attempt to auto-negotiate the - * best link mode if the PHY supports it. If this is not enabled, - * the PHY_USE_FULL_DUPLEX and PHY_USE_100MBS defines will be - * used to select the link mode. Note that auto-negotiation may - * take a few seconds to complete. - */ -#define PHY_USE_AUTONEG 1 /**< Enables auto-negotiation mode. */ - -/** \brief Sets up the PHY interface to either full duplex operation or - * half duplex operation if PHY_USE_AUTONEG is not enabled. - */ -#define PHY_USE_FULL_DUPLEX 1 /**< Sets duplex mode to full. */ - -/** \brief Sets up the PHY interface to either 100MBS operation or 10MBS - * operation if PHY_USE_AUTONEG is not enabled. - */ -#define PHY_USE_100MBS 1 /**< Sets data rate to 100Mbps. */ - -/** - * @} - */ - -/** @defgroup emac_config EMAC configuration - * - * Configuration options for the LPC EMAC. - * @{ - */ - -/** \brief Selects RMII or MII connection type in the EMAC peripheral - */ -#define LPC_EMAC_RMII 1 /**< Use the RMII or MII driver variant .*/ - -/** \brief Defines the number of descriptors used for RX. This - * must be a minimum value of 2. - */ -#define LPC_NUM_BUFF_RXDESCS 4 - -/** \brief Defines the number of descriptors used for TX. Must - * be a minimum value of 2. - */ -#define LPC_NUM_BUFF_TXDESCS 9 - -/** \brief Set this define to 1 to enable bounce buffers for transmit memory - * buffers that cannot be sent via the zero-copy method. Some chained - * buffers may have a payload address that links to an area of memory that - * cannot be used for transmit DMA operations. If this define is - * set to 1, an extra check will be made with the buffers. If a buffer - * is determined to be non-usable for zero-copy, a temporary bounce - * buffer will be created and used instead. - */ -#define LPC_TX_PBUF_BOUNCE_EN 1 - -/** - * @} - */ - -#endif /* __LPC_EMAC_CONFIG_H */ - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h deleted file mode 100644 index 5c2f314..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy.h +++ /dev/null @@ -1,140 +0,0 @@ -/********************************************************************** -* $Id$ lpc_phy.h 2011-11-20 -*//** -* @file lpc_phy.h -* @brief Common PHY definitions used with all PHYs -* @version 1.0 -* @date 20 Nov. 2011 -* @author NXP MCU SW Application Team -* -* Copyright(C) 2011, NXP Semiconductor -* All rights reserved. -* -*********************************************************************** -* Software that is described herein is for illustrative purposes only -* which provides customers with programming information regarding the -* products. This software is supplied "AS IS" without any warranties. -* NXP Semiconductors assumes no responsibility or liability for the -* use of the software, conveys no license or title under any patent, -* copyright, or mask work right to the product. NXP Semiconductors -* reserves the right to make changes in the software without -* notification. NXP Semiconductors also make no representation or -* warranty that such application will be suitable for the specified -* use without further testing or modification. -**********************************************************************/ - -#ifndef __LPC_PHY_H_ -#define __LPC_PHY_H_ - -/* These PHY functions are usually part of the EMAC driver */ - -/** \brief Phy status update state machine - * - * This function provides a state machine for maintaining the PHY - * status without blocking. It must be occasionally called for the - * PHY status to be maintained. - * - * \param[in] lpc17_emac LPC17 EMAC - */ - -int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac); - -/** \brief Initialize the PHY - * - * This function initializes the PHY. It will block until complete. - * This function is called as part of the EMAC driver - * initialization. Configuration of the PHY at startup is - * controlled by setting up configuration defines in lpc_phy.h. - * - * \param[in] lpc17_emac LPC17 EMAC - * \param[in] rmii If set, configures the PHY for RMII mode - * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT - */ -bool lpc_phy_init(LPC17_EMAC *lpc17_emac, int rmii); - -/** \brief Write a value via the MII link (non-blocking) - * - * This function will write a value on the MII link interface to a PHY - * or a connected device. The function will return immediately without - * a status. Status needs to be polled later to determine if the write - * was successful. - * - * \param[in] PhyReg PHY register to write to - * \param[in] Value Value to write - */ -void lpc_mii_write_noblock(uint32_t PhyReg, uint32_t Value); - -/** \brief Write a value via the MII link (blocking) - * - * This function will write a value on the MII link interface to a PHY - * or a connected device. The function will block until complete. - * - * \param[in] PhyReg PHY register to write to - * \param[in] Value Value to write - * \returns 0 if the write was successful, otherwise !0 - */ -bool lpc_mii_write(uint32_t PhyReg, uint32_t Value); - -/** \brief Reads current MII link busy status - * - * This function will return the current MII link busy status and is meant to - * be used with non-blocking functions for monitor PHY status such as - * connection state. - * - * \returns !0 if the MII link is busy, otherwise 0 - */ -uint32_t lpc_mii_is_busy(void); - -/** \brief Starts a read operation via the MII link (non-blocking) - * - * This function returns the current value in the MII data register. It is - * meant to be used with the non-blocking oeprations. This value should - * only be read after a non-block read command has been issued and the - * MII status has been determined to be good. - * - * \returns The current value in the MII value register - */ -uint32_t lpc_mii_read_data(void); - -/** \brief Starts a read operation via the MII link (non-blocking) - * - * This function will start a read operation on the MII link interface - * from a PHY or a connected device. The function will not block and - * the status mist be polled until complete. Once complete, the data - * can be read. - * - * \param[in] PhyReg PHY register to read from - * \param[in] data Pointer to where to save data read via MII - * \returns 0 if the read was successful, otherwise !0 - * - */ -bool lpc_mii_read(uint32_t PhyReg, uint32_t *data); - -/** \brief Read a value via the MII link (blocking) - * - * This function will read a value on the MII link interface from a PHY - * or a connected device. The function will block until complete. - * - * \param[in] PhyReg PHY register to read from - */ -void lpc_mii_read_noblock(uint32_t PhyReg); - -/** - * This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated duplex mode. - * - * @param[in] full_duplex 0 = half duplex, 1 = full duplex - */ -void lpc_emac_set_duplex(int full_duplex); - -/** - * This function provides a method for the PHY to setup the EMAC - * for the PHY negotiated bit rate. - * - * @param[in] mbs_100 0 = 10mbs mode, 1 = 100mbs mode - */ -void lpc_emac_set_speed(int mbs_100); - -#endif /* __LPC_PHY_H_ */ - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp deleted file mode 100644 index 3cc40d3..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc_phy_dp83848.cpp +++ /dev/null @@ -1,433 +0,0 @@ -/********************************************************************** -* $Id$ lpc_phy_dp83848.c 2011-11-20 -*//** -* @file lpc_phy_dp83848.c -* @brief DP83848C PHY status and control. -* @version 1.0 -* @date 20 Nov. 2011 -* @author NXP MCU SW Application Team -* -* Copyright(C) 2011, NXP Semiconductor -* All rights reserved. -* -*********************************************************************** -* Software that is described herein is for illustrative purposes only -* which provides customers with programming information regarding the -* products. This software is supplied "AS IS" without any warranties. -* NXP Semiconductors assumes no responsibility or liability for the -* use of the software, conveys no license or title under any patent, -* copyright, or mask work right to the product. NXP Semiconductors -* reserves the right to make changes in the software without -* notification. NXP Semiconductors also make no representation or -* warranty that such application will be suitable for the specified -* use without further testing or modification. -**********************************************************************/ - -#include "netsocket/nsapi_types.h" -#include "lpc_emac_config.h" -#include "lpc17_emac.h" -#include "lpc_phy.h" -#include "lpc17xx_emac.h" - - -/** @defgroup dp83848_phy PHY status and control for the DP83848. - * @ingroup lwip_phy - * - * Various functions for controlling and monitoring the status of the - * DP83848 PHY. In polled (standalone) systems, the PHY state must be - * monitored as part of the application. In a threaded (RTOS) system, - * the PHY state is monitored by the PHY handler thread. The MAC - * driver will not transmit unless the PHY link is active. - * @{ - */ - -/** \brief DP83848 PHY register offsets */ -#define DP8_BMCR_REG 0x0 /**< Basic Mode Control Register */ -#define DP8_BMSR_REG 0x1 /**< Basic Mode Status Reg */ -#define DP8_IDR1_REG 0x2 /**< Basic Mode Status Reg */ -#define DP8_IDR2_REG 0x3 /**< Basic Mode Status Reg */ -#define DP8_ANADV_REG 0x4 /**< Auto_Neg Advt Reg */ -#define DP8_ANLPA_REG 0x5 /**< Auto_neg Link Partner Ability Reg */ -#define DP8_ANEEXP_REG 0x6 /**< Auto-neg Expansion Reg */ -#define DP8_PHY_STAT_REG 0x10 /**< PHY Status Register */ -#define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */ -#define DP8_PHY_RBR_REG 0x17 /**< PHY RMII and Bypass Register */ -#define DP8_PHY_STS_REG 0x19 /**< PHY Status Register */ - -#define DP8_PHY_SCSR_REG 0x1f /**< PHY Special Control/Status Register (LAN8720) */ - -/** \brief DP83848 Control register definitions */ -#define DP8_RESET (1 << 15) /**< 1= S/W Reset */ -#define DP8_LOOPBACK (1 << 14) /**< 1=loopback Enabled */ -#define DP8_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */ -#define DP8_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */ -#define DP8_POWER_DOWN (1 << 11) /**< 1=Power down PHY */ -#define DP8_ISOLATE (1 << 10) /**< 1=Isolate PHY */ -#define DP8_RESTART_AUTONEG (1 << 9) /**< 1=Restart auto-negoatiation */ -#define DP8_DUPLEX_MODE (1 << 8) /**< 1=Full duplex mode */ -#define DP8_COLLISION_TEST (1 << 7) /**< 1=Perform collsion test */ - -/** \brief DP83848 Status register definitions */ -#define DP8_100BASE_T4 (1 << 15) /**< T4 mode */ -#define DP8_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */ -#define DP8_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */ -#define DP8_10BASE_T_FD (1 << 12) /**< 100Bps full duplex */ -#define DP8_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */ -#define DP8_MF_PREAMB_SUPPR (1 << 6) /**< Preamble suppress */ -#define DP8_AUTONEG_COMP (1 << 5) /**< Auto-negotation complete */ -#define DP8_RMT_FAULT (1 << 4) /**< Fault */ -#define DP8_AUTONEG_ABILITY (1 << 3) /**< Auto-negotation supported */ -#define DP8_LINK_STATUS (1 << 2) /**< 1=Link active */ -#define DP8_JABBER_DETECT (1 << 1) /**< Jabber detect */ -#define DP8_EXTEND_CAPAB (1 << 0) /**< Supports extended capabilities */ - -/** \brief DP83848 PHY RBR MII dode definitions */ -#define DP8_RBR_RMII_MODE (1 << 5) /**< Use RMII mode */ - -/** \brief DP83848 PHY status definitions */ -#define DP8_REMOTEFAULT (1 << 6) /**< Remote fault */ -#define DP8_FULLDUPLEX (1 << 2) /**< 1=full duplex */ -#define DP8_SPEED10MBPS (1 << 1) /**< 1=10MBps speed */ -#define DP8_VALID_LINK (1 << 0) /**< 1=Link active */ - -/** \brief DP83848 PHY ID register definitions */ -#define DP8_PHYID1_OUI 0x2000 /**< Expected PHY ID1 */ -#define DP8_PHYID2_OUI 0x5c90 /**< Expected PHY ID2 */ - -/** \brief LAN8720 PHY Special Control/Status Register */ -#define PHY_SCSR_100MBIT 0x0008 /**< Speed: 1=100 MBit, 0=10Mbit */ -#define PHY_SCSR_DUPLEX 0x0010 /**< PHY Duplex Mask */ - -/** \brief Link status bits */ -#define LNK_STAT_VALID 0x01 -#define LNK_STAT_FULLDUPLEX 0x02 -#define LNK_STAT_SPEED10MPS 0x04 - -/** \brief PHY ID definitions */ -#define DP83848C_ID 0x20005C90 /**< PHY Identifier - DP83848C */ -#define LAN8720_ID 0x0007C0F0 /**< PHY Identifier - LAN8720 */ -#define KSZ8041_ID 0x00221510 /**< PHY Identifier - KSZ8041 */ - - -/** \brief PHY status structure used to indicate current status of PHY. - */ -typedef struct { - unsigned int phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */ - unsigned int phy_full_duplex:1; /**< Half/full duplex connection speed flag. */ - unsigned int phy_link_active:1; /**< Phy link active flag. */ -} PHY_STATUS_TYPE; - -/** \brief PHY update flags */ -static PHY_STATUS_TYPE physts; - -/** \brief Last PHY update flags, used for determing if something has changed */ -static PHY_STATUS_TYPE olddphysts; - -/** \brief PHY update counter for state machine */ -static int32_t phyustate; - -/** \brief Holds the PHY ID */ -static uint32_t phy_id; - -/** \brief Temporary holder of link status for LAN7420 */ -static uint32_t phy_lan7420_sts_tmp; - -/* Write a value via the MII link (non-blocking) */ -void lpc_mii_write_noblock(uint32_t PhyReg, uint32_t Value) -{ - /* Write value at PHY address and register */ - LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg; - LPC_EMAC->MWTD = Value; -} - -/* Write a value via the MII link (blocking) */ -bool lpc_mii_write(uint32_t PhyReg, uint32_t Value) -{ - uint32_t mst = 250; - int8_t sts = 0; - - /* Write value at PHY address and register */ - lpc_mii_write_noblock(PhyReg, Value); - - /* Wait for unbusy status */ - while (mst > 0) { - sts = LPC_EMAC->MIND; - if ((sts & EMAC_MIND_BUSY) == 0) - mst = 0; - else { - mst--; - osDelay(1); - } - } - - if (sts != 0) - return false; - - return true; -} - -/* Reads current MII link busy status */ -uint32_t lpc_mii_is_busy(void) -{ - return (uint32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY); -} - -/* Starts a read operation via the MII link (non-blocking) */ -uint32_t lpc_mii_read_data(void) -{ - uint32_t data = LPC_EMAC->MRDD; - LPC_EMAC->MCMD = 0; - - return data; -} - -/* Starts a read operation via the MII link (non-blocking) */ -void lpc_mii_read_noblock(uint32_t PhyReg) -{ - /* Read value at PHY address and register */ - LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg; - LPC_EMAC->MCMD = EMAC_MCMD_READ; -} - -/* Read a value via the MII link (blocking) */ -bool lpc_mii_read(uint32_t PhyReg, uint32_t *data) -{ - uint32_t mst = 250; - int8_t sts = 0; - - /* Read value at PHY address and register */ - lpc_mii_read_noblock(PhyReg); - - /* Wait for unbusy status */ - while (mst > 0) { - sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL; - if ((sts & EMAC_MIND_BUSY) == 0) { - mst = 0; - *data = LPC_EMAC->MRDD; - } else { - mst--; - osDelay(1); - } - } - - LPC_EMAC->MCMD = 0; - - if (sts != 0) - return false; - - return true; -} - -/** \brief Update PHY status from passed value - * - * This function updates the current PHY status based on the - * passed PHY status word. The PHY status indicate if the link - * is active, the connection speed, and duplex. - * - * \param[in] lpc17_emac LPC17 EMAC - * \param[in] linksts Status word from PHY - * \return 1 if the status has changed, otherwise 0 - */ -static int32_t lpc_update_phy_sts(LPC17_EMAC *lpc17_emac, uint32_t linksts) -{ - int32_t changed = 0; - - /* Update link active status */ - if (linksts & LNK_STAT_VALID) - physts.phy_link_active = 1; - else - physts.phy_link_active = 0; - - /* Full or half duplex */ - if (linksts & LNK_STAT_FULLDUPLEX) - physts.phy_full_duplex = 1; - else - physts.phy_full_duplex = 0; - - /* Configure 100MBit/10MBit mode. */ - if (linksts & LNK_STAT_SPEED10MPS) - physts.phy_speed_100mbs = 0; - else - physts.phy_speed_100mbs = 1; - - if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) { - changed = 1; - if (physts.phy_speed_100mbs) { - /* 100MBit mode. */ - lpc_emac_set_speed(1); - } - else { - /* 10MBit mode. */ - lpc_emac_set_speed(0); - } - - olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs; - } - - if (physts.phy_full_duplex != olddphysts.phy_full_duplex) { - changed = 1; - if (physts.phy_full_duplex) - lpc_emac_set_duplex(1); - else - lpc_emac_set_duplex(0); - - olddphysts.phy_full_duplex = physts.phy_full_duplex; - } - - if (physts.phy_link_active != olddphysts.phy_link_active) { - changed = 1; - - if (physts.phy_link_active) { - lpc17_emac->update_link_status(true); - } else { - lpc17_emac->update_link_status(false); - } - - olddphysts.phy_link_active = physts.phy_link_active; - } - - return changed; -} - -/** \brief Initialize the DP83848 PHY. - * - * This function initializes the DP83848 PHY. It will block until - * complete. This function is called as part of the EMAC driver - * initialization. Configuration of the PHY at startup is - * controlled by setting up configuration defines in lpc_phy.h. - * - * \param[in] lpc17_emac LPC17 EMAC - * \param[in] rmii If set, configures the PHY for RMII mode - * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT - */ -bool lpc_phy_init(LPC17_EMAC *lpc17_emac, int rmii) -{ - uint32_t tmp; - int32_t i; - - physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0; - physts.phy_full_duplex = olddphysts.phy_full_duplex = 0; - physts.phy_link_active = olddphysts.phy_link_active = 0; - phyustate = 0; - - /* Only first read and write are checked for failure */ - /* Put the DP83848C in reset mode and wait for completion */ - if (!lpc_mii_write(DP8_BMCR_REG, DP8_RESET)) { - return false; - } - i = 400; - while (i > 0) { - osDelay(1); /* 1 ms */ - if (!lpc_mii_read(DP8_BMCR_REG, &tmp)) - return false; - - if (!(tmp & (DP8_RESET | DP8_POWER_DOWN))) - i = -1; - else - i--; - } - /* Timeout? */ - if (i == 0) - return false; - - // read PHY ID - lpc_mii_read(DP8_IDR1_REG, &tmp); - phy_id = (tmp << 16); - lpc_mii_read(DP8_IDR2_REG, &tmp); - phy_id |= (tmp & 0XFFF0); - - /* Setup link based on configuration options */ -#if PHY_USE_AUTONEG==1 - tmp = DP8_AUTONEG; -#else - tmp = 0; -#endif -#if PHY_USE_100MBS==1 - tmp |= DP8_SPEED_SELECT; -#endif -#if PHY_USE_FULL_DUPLEX==1 - tmp |= DP8_DUPLEX_MODE; -#endif - lpc_mii_write(DP8_BMCR_REG, tmp); - - /* Enable RMII mode for PHY */ - if (rmii) { - /* Mode is set with config pins on KSZ8041 */ - if (phy_id != KSZ8041_ID) - lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE); - } - /* The link is not set active at this point, but will be detected - later */ - - return true; -} - -/** \brief Phy status update state machine - * - * \param[in] lpc17_emac LPC17 EMAC - * \return 1 if the status has changed, otherwise 0 - */ -int32_t lpc_phy_sts_sm(LPC17_EMAC *lpc17_emac) -{ - int32_t changed = 0; - uint32_t data = 0; - uint32_t tmp; - - switch (phyustate) { - default: - case 0: - if (phy_id == DP83848C_ID) { - lpc_mii_read_noblock(DP8_PHY_STAT_REG); - phyustate = 2; - } - else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { - lpc_mii_read_noblock(DP8_PHY_SCSR_REG); - phyustate = 1; - } - break; - - case 1: - if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { - tmp = lpc_mii_read_data(); - // we get speed and duplex here. - phy_lan7420_sts_tmp = (tmp & PHY_SCSR_DUPLEX) ? LNK_STAT_FULLDUPLEX : 0; - phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS; - - //read the status register to get link status - lpc_mii_read_noblock(DP8_BMSR_REG); - phyustate = 2; - } - break; - - case 2: - /* Wait for read status state */ - if (!lpc_mii_is_busy()) { - /* Update PHY status */ - tmp = lpc_mii_read_data(); - - if (phy_id == DP83848C_ID) { - // STS register contains all needed status bits - data = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0; - data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0; - data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0; - } - else if (phy_id == LAN8720_ID || phy_id == KSZ8041_ID) { - // we only get the link status here. - phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0; - data = phy_lan7420_sts_tmp; - } - - changed = lpc_update_phy_sts(lpc17_emac, data); - phyustate = 0; - } - break; - } - - return changed; -} - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c deleted file mode 100644 index 096689e..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_FF_LPC546XX/hardware_init_LPC546XX.c +++ /dev/null @@ -1,227 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "fsl_iocon.h" - -#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ -#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ -#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */ -#define IOCON_PIO_FUNC6 0x06u /*!<@brief Selects pin function 6 */ -#define IOCON_PIO_FUNC7 0x07u /*!<@brief Selects pin function 7 */ -#define IOCON_PIO_INPFILT_OFF 0x0200u /*!<@brief Input filter disabled */ -#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ -#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */ -#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ -#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ -#define IOCON_PIO_SLEW_FAST 0x0400u /*!<@brief Fast mode, slew rate control is disabled */ -#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ - -/******************************************************************************* - * Code - ******************************************************************************/ -void lpc546xx_init_eth_hardware(void) -{ - CLOCK_EnableClock(kCLOCK_InputMux); - - /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */ - CLOCK_EnableClock(kCLOCK_Iocon); - - const uint32_t port0_pin10_config = (/* Pin is configured as SWO */ - IOCON_PIO_FUNC6 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT0 PIN10 (coords: P2) is configured as SWO */ - IOCON_PinMuxSet(IOCON, 0U, 10U, port0_pin10_config); - - const uint32_t port1_pin10_config = (/* Pin is configured as ENET_TXD1 */ - IOCON_PIO_FUNC1 /* IOCON_PIO_FUNC1 */ | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT1 PIN10 (coords: E14) is configured as ENET_TXD1 */ - IOCON_PinMuxSet(IOCON, 1U, 10U, port1_pin10_config); - - - const uint32_t port1_pin18_config = (/* Pin is configured as ENET_PHY_RST */ - IOCON_PIO_FUNC0 | - /* Selects pull-up function */ - IOCON_PIO_MODE_PULLUP | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT1 PIN18 (coords: H11) is configured as ENET_PHY_RST */ - IOCON_PinMuxSet(IOCON, 1U, 18U, port1_pin18_config); - - const uint32_t port1_pin14_config = (/* Pin is configured as ENET_RX_DV */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT1 PIN14 (coords: B9) is configured as ENET_RX_DV */ - IOCON_PinMuxSet(IOCON, 1U, 14U, port1_pin14_config); - - const uint32_t port1_pin12_config = (/* Pin is configured as ENET_RXD0 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT1 PIN12 (coords: A9) is configured as ENET_RXD0 */ - IOCON_PinMuxSet(IOCON, 1U, 12U, port1_pin12_config); - - const uint32_t port1_pin13_config = (/* Pin is configured as ENET_RXD1 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */ - IOCON_PinMuxSet(IOCON, 1U, 13U, port1_pin13_config); - - const uint32_t port1_pin11_config = (/* Pin is configured as ENET_TX_EN */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */ - IOCON_PinMuxSet(IOCON, 1U, 11U, port1_pin11_config); - - const uint32_t port1_pin15_config = (/* Pin is configured as ENET_RX_CLK */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */ - IOCON_PinMuxSet(IOCON, 1U, 15U, port1_pin15_config); - - const uint32_t port1_pin16_config = (/* Pin is configured as ENET_MDC */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */ - IOCON_PinMuxSet(IOCON, 1U, 16U, port1_pin16_config); - - const uint32_t port1_pin17_config = (/* Pin is configured as ENET_MDIO */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */ - IOCON_PinMuxSet(IOCON, 1U, 17U, port1_pin17_config); - - const uint32_t port1_pin9_config = (/* Pin is configured as ENET_TXD0 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */ - IOCON_PinMuxSet(IOCON, 1U, 9U, port1_pin9_config); -} diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c deleted file mode 100644 index 22836f9..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/TARGET_LPCXpresso/hardware_init_LPC546XX.c +++ /dev/null @@ -1,261 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "fsl_iocon.h" - -#define IOCON_PIO_DIGITAL_EN 0x0100u /*!<@brief Enables digital function */ -#define IOCON_PIO_FUNC0 0x00u /*!<@brief Selects pin function 0 */ -#define IOCON_PIO_FUNC1 0x01u /*!<@brief Selects pin function 1 */ -#define IOCON_PIO_FUNC6 0x06u /*!<@brief Selects pin function 6 */ -#define IOCON_PIO_FUNC7 0x07u /*!<@brief Selects pin function 7 */ -#define IOCON_PIO_INPFILT_OFF 0x0200u /*!<@brief Input filter disabled */ -#define IOCON_PIO_INV_DI 0x00u /*!<@brief Input function is not inverted */ -#define IOCON_PIO_MODE_INACT 0x00u /*!<@brief No addition pin function */ -#define IOCON_PIO_MODE_PULLUP 0x20u /*!<@brief Selects pull-up function */ -#define IOCON_PIO_OPENDRAIN_DI 0x00u /*!<@brief Open drain is disabled */ -#define IOCON_PIO_SLEW_FAST 0x0400u /*!<@brief Fast mode, slew rate control is disabled */ -#define IOCON_PIO_SLEW_STANDARD 0x00u /*!<@brief Standard mode, output slew rate control is enabled */ - -/******************************************************************************* - * Code - ******************************************************************************/ -void lpc546xx_init_eth_hardware(void) -{ - CLOCK_EnableClock(kCLOCK_InputMux); - - /* Enables the clock for the IOCON block. 0 = Disable; 1 = Enable.: 0x01u */ - CLOCK_EnableClock(kCLOCK_Iocon); - - const uint32_t port0_pin10_config = (/* Pin is configured as SWO */ - IOCON_PIO_FUNC6 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT0 PIN10 (coords: P2) is configured as SWO */ - IOCON_PinMuxSet(IOCON, 0U, 10U, port0_pin10_config); - - const uint32_t port0_pin17_config = (/* Pin is configured as ENET_TXD1 */ - IOCON_PIO_FUNC7 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT0 PIN17 (coords: E14) is configured as ENET_TXD1 */ - IOCON_PinMuxSet(IOCON, 0U, 17U, port0_pin17_config); - - const uint32_t port0_pin29_config = (/* Pin is configured as FC0_RXD_SDA_MOSI */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Fast mode, slew rate control is disabled */ - IOCON_PIO_SLEW_FAST | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT0 PIN29 (coords: B13) is configured as FC0_RXD_SDA_MOSI */ - IOCON_PinMuxSet(IOCON, 0U, 29U, port0_pin29_config); - - const uint32_t port0_pin30_config = (/* Pin is configured as FC0_TXD_SCL_MISO */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Fast mode, slew rate control is disabled */ - IOCON_PIO_SLEW_FAST | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT0 PIN30 (coords: A2) is configured as FC0_TXD_SCL_MISO */ - IOCON_PinMuxSet(IOCON, 0U, 30U, port0_pin30_config); - - const uint32_t port2_pin26_config = (/* Pin is configured as PIO2_26 */ - IOCON_PIO_FUNC0 | - /* Selects pull-up function */ - IOCON_PIO_MODE_PULLUP | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT2 PIN26 (coords: H11) is configured as PIO2_26 */ - IOCON_PinMuxSet(IOCON, 2U, 26U, port2_pin26_config); - - const uint32_t port4_pin10_config = (/* Pin is configured as ENET_RX_DV */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN10 (coords: B9) is configured as ENET_RX_DV */ - IOCON_PinMuxSet(IOCON, 4U, 10U, port4_pin10_config); - - const uint32_t port4_pin11_config = (/* Pin is configured as ENET_RXD0 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN11 (coords: A9) is configured as ENET_RXD0 */ - IOCON_PinMuxSet(IOCON, 4U, 11U, port4_pin11_config); - - const uint32_t port4_pin12_config = (/* Pin is configured as ENET_RXD1 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN12 (coords: A6) is configured as ENET_RXD1 */ - IOCON_PinMuxSet(IOCON, 4U, 12U, port4_pin12_config); - - const uint32_t port4_pin13_config = (/* Pin is configured as ENET_TX_EN */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN13 (coords: B6) is configured as ENET_TX_EN */ - IOCON_PinMuxSet(IOCON, 4U, 13U, port4_pin13_config); - - const uint32_t port4_pin14_config = (/* Pin is configured as ENET_RX_CLK */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN14 (coords: B5) is configured as ENET_RX_CLK */ - IOCON_PinMuxSet(IOCON, 4U, 14U, port4_pin14_config); - - const uint32_t port4_pin15_config = (/* Pin is configured as ENET_MDC */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN15 (coords: A4) is configured as ENET_MDC */ - IOCON_PinMuxSet(IOCON, 4U, 15U, port4_pin15_config); - - const uint32_t port4_pin16_config = (/* Pin is configured as ENET_MDIO */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN16 (coords: C4) is configured as ENET_MDIO */ - IOCON_PinMuxSet(IOCON, 4U, 16U, port4_pin16_config); - - const uint32_t port4_pin8_config = (/* Pin is configured as ENET_TXD0 */ - IOCON_PIO_FUNC1 | - /* No addition pin function */ - IOCON_PIO_MODE_INACT | - /* Input function is not inverted */ - IOCON_PIO_INV_DI | - /* Enables digital function */ - IOCON_PIO_DIGITAL_EN | - /* Input filter disabled */ - IOCON_PIO_INPFILT_OFF | - /* Standard mode, output slew rate control is enabled */ - IOCON_PIO_SLEW_STANDARD | - /* Open drain is disabled */ - IOCON_PIO_OPENDRAIN_DI); - /* PORT4 PIN8 (coords: B14) is configured as ENET_TXD0 */ - IOCON_PinMuxSet(IOCON, 4U, 8U, port4_pin8_config); -} - diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp deleted file mode 100644 index 9b0b9df..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.cpp +++ /dev/null @@ -1,605 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "cmsis_os.h" - -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" - -#include "fsl_phy.h" - -#include "lpc546xx_emac_config.h" -#include "lpc546xx_emac.h" - -using namespace std::chrono; - -enet_handle_t g_handle; -// RX packet buffer pointers -emac_mem_buf_t *rx_buff[ENET_RX_RING_LEN]; -// TX packet buffer pointers -emac_mem_buf_t *tx_buff[ENET_TX_RING_LEN]; -// RX packet payload pointers -uint32_t rx_ptr[ENET_RX_RING_LEN]; - -/******************************************************************************** - * Internal data - ********************************************************************************/ -#define ENET_BuffSizeAlign(n) ENET_ALIGN(n, ENET_BUFF_ALIGNMENT) -#define ENET_ALIGN(x,align) ((unsigned int)((x) + ((align)-1)) & (unsigned int)(~(unsigned int)((align)- 1))) - -extern "C" void lpc546xx_init_eth_hardware(void); - -/* \brief Flags for worker thread */ -#define FLAG_TX 1 -#define FLAG_RX 2 - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityNormal) - -#define PHY_TASK_PERIOD 200ms - -LPC546XX_EMAC::LPC546XX_EMAC() : xTXDCountSem(ENET_TX_RING_LEN, ENET_TX_RING_LEN), hwaddr() -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} - -/******************************************************************************** - * Buffer management - ********************************************************************************/ -/* - * This function will queue a new receive buffer - */ -static void update_read_buffer(enet_rx_bd_struct_t *rxDesc, uint8_t *buf) -{ - enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; - uint32_t control = ENET_RXDESCRIP_RD_OWN_MASK | ENET_RXDESCRIP_RD_BUFF1VALID_MASK | ENET_RXDESCRIP_RD_IOC_MASK; - uint32_t index = rxBdRing->rxGenIdx; - /* Increase the index. */ - index++; - if (index >= ENET_RX_RING_LEN) { - index = 0; - } - - rxBdRing->rxGenIdx = index; - if (buf != NULL) { - rxDesc->buff1Addr = (uint32_t)buf; - } - - rxDesc->buff2Addr = 0; - rxDesc->reserved = 0; - rxDesc->control = control; -} - -/** \brief Free TX buffers that are complete - */ -void LPC546XX_EMAC::tx_reclaim() -{ - /* Get exclusive access */ - TXLockMutex.lock(); - - static uint8_t consume_index = 0; - enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)&g_handle.txBdRing[0]; - - while (consume_index != txBdRing->txConsumIdx) { - /* Free the transmit buffer */ - memory_manager->free(tx_buff[consume_index]); - tx_buff[consume_index] = NULL; - - xTXDCountSem.release(); - - consume_index++; - if (consume_index >= ENET_TX_RING_LEN) { - consume_index = 0; - } - } - /* Restore access */ - TXLockMutex.unlock(); -} - -/** \brief Ethernet receive interrupt handler - * - * This function handles the receive interrupt of LPC546XX. - */ -void LPC546XX_EMAC::rx_isr() -{ - osThreadFlagsSet(thread, FLAG_RX); -} - -void LPC546XX_EMAC::tx_isr() -{ - osThreadFlagsSet(thread, FLAG_TX); -} - -void LPC546XX_EMAC::ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param) -{ - LPC546XX_EMAC *enet = static_cast(param); - - switch (event) { - case kENET_RxIntEvent: - enet->rx_isr(); - break; - case kENET_TxIntEvent: - enet->tx_isr(); - break; - default: - break; - } -} - -/** \brief Low level init of the MAC and PHY. - */ -bool LPC546XX_EMAC::low_level_init_successful() -{ - status_t status; - uint8_t i; - uint32_t refClock; - phy_speed_t phy_speed; - phy_duplex_t phy_duplex; - uint32_t phyAddr = 0; - bool link = false; - enet_config_t config; - uint32_t timeout = 0xFFFU; - - lpc546xx_init_eth_hardware(); - - refClock = CLOCK_GetFreq(kCLOCK_CoreSysClk); - - status = PHY_Init(ENET, phyAddr, refClock); - if (status != kStatus_Success) { - return false; - } - - ENET_GetDefaultConfig(&config); - config.multiqueueCfg = NULL; - - while ((!link) && timeout) { - PHY_GetLinkStatus(ENET, phyAddr, &link); - if (link) { - /* Get link information from PHY */ - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &phy_speed, &phy_duplex); - - /* Change the MII speed and duplex for actual link status. */ - config.miiSpeed = (enet_mii_speed_t)phy_speed; - config.miiDuplex = (enet_mii_duplex_t)phy_duplex; - } - timeout--; - } - - if (!link) { - return false; - } - - AT_NONCACHEABLE_SECTION_ALIGN(static enet_rx_bd_struct_t rx_desc_start_addr[ENET_RX_RING_LEN], ENET_BUFF_ALIGNMENT); - AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t tx_desc_start_addr[ENET_TX_RING_LEN], ENET_BUFF_ALIGNMENT); - - /* prepare the buffer configuration. */ - enet_buffer_config_t buffCfg = { - ENET_RX_RING_LEN, - ENET_TX_RING_LEN, - &tx_desc_start_addr[0], - &tx_desc_start_addr[0], - &rx_desc_start_addr[0], - &rx_desc_start_addr[ENET_RX_RING_LEN], - rx_ptr, - ENET_BuffSizeAlign(ENET_ETH_MAX_FLEN), - }; - - /* Create buffers for each receive BD */ - for (i = 0; i < ENET_RX_RING_LEN; i++) { - rx_buff[i] = memory_manager->alloc_heap(buffCfg.rxBuffSizeAlign, ENET_BUFF_ALIGNMENT); - if (NULL == rx_buff[i]) { - return false; - } - - rx_ptr[i] = (uint32_t)memory_manager->get_ptr(rx_buff[i]); - } - - ENET_Init(ENET, &config, hwaddr, refClock); - - /* Enable the tx & rx interrupt. */ - ENET_EnableInterrupts(ENET, kENET_DmaTx | kENET_DmaRx); - - /* Create the handler. */ - ENET_CreateHandler(ENET, &g_handle, &config, &buffCfg, &LPC546XX_EMAC::ethernet_callback, this); - - /* Initialize Descriptor. */ - ENET_DescriptorInit(ENET, &config, &buffCfg); - - return true; -} - -/** \brief Allocates a emac_mem_buf_t and returns the data from the incoming packet. - * - * \return a emac_mem_buf_t filled with the received packet (including MAC header) - * NULL on memory error - */ -emac_mem_buf_t *LPC546XX_EMAC::low_level_input() -{ - enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; - enet_rx_bd_struct_t *bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; - emac_mem_buf_t *p = NULL; - emac_mem_buf_t *temp_rxbuf = NULL; - uint32_t length = 0; - - /* Determine if a frame has been received */ - if ((bdPtr->control & ENET_RXDESCRIP_WR_OWN_MASK) != 0) { - return p; - } - -#ifdef LOCK_RX_THREAD - /* Get exclusive access */ - TXLockMutex.lock(); -#endif - - /* Determine if the received frame has an error */ - if ((bdPtr->control & ENET_RXDESCRIP_WR_ERRSUM_MASK) != 0) { - /* Re-use the same buffer in case of error */ - update_read_buffer(bdPtr, NULL); - } else { - if (bdPtr->control & ENET_RXDESCRIP_WR_LD_MASK) { - length = (bdPtr->control & ENET_RXDESCRIP_WR_PACKETLEN_MASK) - 4; - } else { - length = rxBdRing->rxBuffSizeAlign; - } - - /* Zero-copy */ - p = rx_buff[rxBdRing->rxGenIdx]; - memory_manager->set_len(p, length); - - /* Attempt to queue new buffer */ - temp_rxbuf = memory_manager->alloc_heap(rxBdRing->rxBuffSizeAlign, ENET_BUFF_ALIGNMENT); - if (NULL == temp_rxbuf) { - /* Re-queue the same buffer */ - update_read_buffer(bdPtr, NULL); - -#ifdef LOCK_RX_THREAD - TXLockMutex.unlock(); -#endif - - return NULL; - } - - rx_buff[rxBdRing->rxGenIdx] = temp_rxbuf; - rx_ptr[rxBdRing->rxGenIdx] = (uint32_t)memory_manager->get_ptr(rx_buff[rxBdRing->rxGenIdx]); - - update_read_buffer(bdPtr, (uint8_t *)rx_ptr[rxBdRing->rxGenIdx]); - } - -#ifdef LOCK_RX_THREAD - osMutexRelease(TXLockMutex); -#endif - - return p; -} - -/** \brief Attempt to read a packet from the EMAC interface. - */ -void LPC546XX_EMAC::input() -{ - emac_mem_buf_t *p; - - /* move received packet into a new pbuf */ - p = low_level_input(); - if (p == NULL) { - return; - } - - emac_link_input_cb(p); -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void LPC546XX_EMAC::thread_function(void *pvParameters) -{ - struct LPC546XX_EMAC *lpc_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX | FLAG_TX, osFlagsWaitAny, osWaitForever); - - MBED_ASSERT(!(flags & osFlagsError)); - - if (flags & FLAG_RX) { - lpc_enet->packet_rx(); - } - - if (flags & FLAG_TX) { - lpc_enet->packet_tx(); - } - } -} - -/** \brief Packet reception task - * - * This task is called when a packet is received. It will - * pass the packet to the LWIP core. - */ -void LPC546XX_EMAC::packet_rx() -{ - enet_rx_bd_ring_t *rxBdRing = (enet_rx_bd_ring_t *)&g_handle.rxBdRing[0]; - enet_rx_bd_struct_t *bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; - bool suspend = false; - - /* Suspend and command for rx. */ - if (ENET->DMA_CH[0].DMA_CHX_STAT & ENET_DMA_CH_DMA_CHX_STAT_RBU_MASK) { - suspend = true; - } - - while ((bdPtr->control & ENET_RXDESCRIP_WR_OWN_MASK) == 0) { - input(); - /* rxGenIdx gets updated, gets the next receive buffer descriptor */ - bdPtr = rxBdRing->rxBdBase + rxBdRing->rxGenIdx; - } - - /* Set command for rx when it is suspend. */ - if (suspend) { - ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR = ENET->DMA_CH[0].DMA_CHX_RXDESC_TAIL_PTR; - } -} - -/** \brief Transmit cleanup task - * - * This task is called when a transmit interrupt occurs and - * reclaims the buffer and descriptor used for the packet once - * the packet has been transferred. - */ -void LPC546XX_EMAC::packet_tx() -{ - tx_reclaim(); -} - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - */ -bool LPC546XX_EMAC::link_out(emac_mem_buf_t *buf) -{ - enet_tx_bd_ring_t *txBdRing = (enet_tx_bd_ring_t *)&g_handle.txBdRing[0]; - uint32_t index = txBdRing->txGenIdx; - - // If buffer is chained or not aligned then make a contiguous aligned copy of it - if (memory_manager->get_next(buf) || - reinterpret_cast(memory_manager->get_ptr(buf)) % ENET_BUFF_ALIGNMENT) { - emac_mem_buf_t *copy_buf; - copy_buf = memory_manager->alloc_heap(memory_manager->get_total_len(buf), ENET_BUFF_ALIGNMENT); - if (NULL == copy_buf) { - memory_manager->free(buf); - return false; - } - - // Copy to new buffer and free original - memory_manager->copy(copy_buf, buf); - memory_manager->free(buf); - buf = copy_buf; - } - - /* Check if a descriptor is available for the transfer. */ - if (!xTXDCountSem.try_acquire()) { - memory_manager->free(buf); - return false; - } - - /* Get exclusive access */ - TXLockMutex.lock(); - - /* Save the buffer so that it can be freed when transmit is done */ - tx_buff[index] = buf; - - if (ENET_SendFrame(ENET, &g_handle, static_cast(memory_manager->get_ptr(buf)), memory_manager->get_len(buf)) != kStatus_Success) { - memory_manager->free(buf); - tx_buff[index] = NULL; - return false; - } - - /* Restore access */ - TXLockMutex.unlock(); - - return true; -} - -/******************************************************************************* - * PHY task: monitor link -*******************************************************************************/ - -#define STATE_UNKNOWN (-1) - -int phy_link_status(void) -{ - bool connection_status; - uint32_t phyAddr = 0; - - PHY_GetLinkStatus(ENET, phyAddr, &connection_status); - return (int)connection_status; -} - -void LPC546XX_EMAC::phy_task() -{ - static PHY_STATE prev_state = {STATE_UNKNOWN, (phy_speed_t)STATE_UNKNOWN, (phy_duplex_t)STATE_UNKNOWN}; - uint32_t phyAddr = 0; - // Get current status - PHY_STATE crt_state; - bool connection_status; - - PHY_GetLinkStatus(ENET, phyAddr, &connection_status); - crt_state.connected = connection_status; - // Get the actual PHY link speed - PHY_GetLinkSpeedDuplex(ENET, phyAddr, &crt_state.speed, &crt_state.duplex); - - // Compare with previous state - if (crt_state.connected != prev_state.connected && emac_link_state_cb) { - emac_link_state_cb(crt_state.connected); - } - - if (crt_state.speed != prev_state.speed) { - uint32_t fes = ENET->MAC_CONFIG; - fes &= ~ENET_MAC_CONFIG_FES_MASK; - if (prev_state.speed != (phy_speed_t)STATE_UNKNOWN) { - fes |= ENET_MAC_CONFIG_FES(!crt_state.speed); - } else { - fes |= ENET_MAC_CONFIG_FES(crt_state.speed); - } - - ENET->MAC_CONFIG = fes; - } - - prev_state = crt_state; -} - -bool LPC546XX_EMAC::power_up() -{ - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - /* Worker thread */ - thread = create_new_thread("LPC546XX_EMAC_thread", &LPC546XX_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); - - /* Trigger thread to deal with any RX packets that arrived before thread was started */ - rx_isr(); - - /* PHY monitoring task */ - prev_state.connected = STATE_UNKNOWN; - prev_state.speed = (phy_speed_t)STATE_UNKNOWN; - prev_state.duplex = (phy_duplex_t)STATE_UNKNOWN; - - phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &LPC546XX_EMAC::phy_task)); - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - /* Active TX/RX. */ - ENET_StartRxTx(ENET, 1, 1); - - return true; -} - -uint32_t LPC546XX_EMAC::get_mtu_size() const -{ - return LPC546XX_ETH_MTU_SIZE; -} - -uint32_t LPC546XX_EMAC::get_align_preference() const -{ - return ENET_BUFF_ALIGNMENT; -} - -void LPC546XX_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, LPC546XX_ETH_IF_NAME, (size < sizeof(LPC546XX_ETH_IF_NAME)) ? size : sizeof(LPC546XX_ETH_IF_NAME)); -} - -uint8_t LPC546XX_EMAC::get_hwaddr_size() const -{ - return LPC546XX_HWADDR_SIZE; -} - -bool LPC546XX_EMAC::get_hwaddr(uint8_t *addr) const -{ - return false; -} - -void LPC546XX_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, sizeof hwaddr); - ENET_SetMacAddr(ENET, const_cast(addr)); -} - -void LPC546XX_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void LPC546XX_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void LPC546XX_EMAC::add_multicast_group(const uint8_t *addr) -{ - set_all_multicast(true); -} - -void LPC546XX_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void LPC546XX_EMAC::set_all_multicast(bool all) -{ - uint32_t reg = ENET->MAC_FRAME_FILTER; - - if (all) { - reg |= ENET_MAC_FRAME_FILTER_PM_MASK; - } else { - reg &= ~ENET_MAC_FRAME_FILTER_PM_MASK; - } - - ENET->MAC_FRAME_FILTER = reg; -} - -void LPC546XX_EMAC::power_down() -{ - /* No-op at this stage */ -} - -void LPC546XX_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - - -LPC546XX_EMAC &LPC546XX_EMAC::get_instance() -{ - static LPC546XX_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return LPC546XX_EMAC::get_instance(); -} - -/** - * @} - */ - -/* --------------------------------- End Of File ------------------------------ */ - diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h deleted file mode 100644 index 570a7a5..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LPC546XX_EMAC_H_ -#define LPC546XX_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -class LPC546XX_EMAC : public EMAC { -public: - LPC546XX_EMAC(); - - static LPC546XX_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - bool low_level_init_successful(); - void rx_isr(); - void tx_isr(); - void packet_rx(); - void packet_tx(); - void tx_reclaim(); - void input(); - emac_mem_buf_t *low_level_input(); - static void thread_function(void* pvParameters); - void phy_task(); - static void ethernet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, uint8_t channel, void *param); - - mbed_rtos_storage_thread_t thread_cb; - osThreadId_t thread; /**< Processing thread */ - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - rtos::Semaphore xTXDCountSem; /**< TX free buffer counting semaphore */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - int phy_task_handle; /**< Handle for phy task event */ - struct PHY_STATE { - int connected; - phy_speed_t speed; - phy_duplex_t duplex; - }; - PHY_STATE prev_state; - uint8_t hwaddr[LPC546XX_HWADDR_SIZE]; -}; - -#endif /* LPC546XX_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h b/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h deleted file mode 100644 index 72df09f..0000000 --- a/features/netsocket/emac-drivers/TARGET_NXP_EMAC/TARGET_MCU_LPC546XX/lpc546xx_emac_config.h +++ /dev/null @@ -1,33 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef LPC546XX_EMAC_CONFIG_H__ -#define LPC546XX_EMAC_CONFIG_H__ - -#include "fsl_enet.h" - -#define ENET_RX_RING_LEN (16) -#define ENET_TX_RING_LEN (8) - -#define ENET_ETH_MAX_FLEN (ENET_FRAME_MAX_FRAMELEN) -#define LPC546XX_HWADDR_SIZE (6) - -#define LPC546XX_ETH_MTU_SIZE 1500 -#define LPC546XX_ETH_IF_NAME "en" - -#define THREAD_STACKSIZE 512 - -#endif // #define LPC546XX_EMAC_CONFIG_H__ - diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp deleted file mode 100644 index c68b732..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/RdaWiFiInterface.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WiFiInterface.h" -#include "RdaWiFiInterface.h" -#include "rda5991h_wland.h" -#include "nsapi_types.h" -#include "wland_types.h" -#include "rda_sys_wrapper.h" - -typedef enum { - WIFI_CONNECTED, - WIFI_DISCONNECTED, -}WIFI_STATE; - -static WIFI_STATE wifi_state = WIFI_DISCONNECTED; - -void daemon(void *para) -{ - void *main_msgQ = NULL; - rda_msg msg; - int ret; - RDAWiFiInterface *wifi = (RDAWiFiInterface *)para; - main_msgQ = rda_mail_create(10, sizeof(unsigned int)*4); - wifi->set_msg_queue(main_msgQ); - while(1){ - rda_mail_get(main_msgQ, (void*)&msg, osWaitForever); - switch(msg.type) - { - case MAIN_RECONNECT: - printf("wifi disconnect!\r\n"); - ret = wifi->disconnect(); - if(ret != 0){ - printf("disconnect failed!\r\n"); - break; - } - ret = wifi->reconnect(); - while(ret != 0){ - osDelay(5*1000); - ret = wifi->reconnect(); - }; - break; - default: - printf("unknown msg\r\n"); - break; - } - } -} - -nsapi_error_t RDAWiFiInterface::set_channel(uint8_t channel) -{ - int ret= 0; - init(); - - if (channel > 13) - return NSAPI_ERROR_PARAMETER; - - if (channel == 0) { - _channel = 0; - return NSAPI_ERROR_OK; - } - - ret = rda5981_set_channel(channel); - if (ret == 0) { - _channel = channel; - return NSAPI_ERROR_OK; - } else { - return NSAPI_ERROR_TIMEOUT; - } -} - -int8_t RDAWiFiInterface::get_rssi() -{ - return rda5981_get_rssi(); -} - -nsapi_error_t RDAWiFiInterface::init() -{ - if (!_interface) { - if (!_emac.power_up()) { - LWIP_DEBUGF(NETIF_DEBUG,("power up failed!\n")); - } - nsapi_error_t err = _stack.add_ethernet_interface(_emac, true, &_interface); - if (err != NSAPI_ERROR_OK) { - _interface = NULL; - return err; - } - _interface->attach(_connection_status_cb); - //rda_thread_new("daemon", daemon, this, DEFAULT_THREAD_STACKSIZE*4, osPriorityNormal); - } - return NSAPI_ERROR_OK; -} - -nsapi_error_t RDAWiFiInterface::set_credentials(const char *ssid, const char *pass, - nsapi_security_t security) -{ - if (ssid == 0 || strlen(ssid) == 0) { - return NSAPI_ERROR_PARAMETER; - } - if (security != NSAPI_SECURITY_NONE && (pass == 0 || strlen(pass) == 0)) { - return NSAPI_ERROR_PARAMETER; - } - if (strlen(ssid) > 32 || strlen(pass) > 63) { - return NSAPI_ERROR_PARAMETER; - } - memcpy((void*)_ssid, (void*)ssid, strlen(ssid)); - _ssid[strlen(ssid)] = '\0'; - memcpy((void*)_pass, (void*)pass, strlen(pass)); - _pass[strlen(pass)] = '\0'; - _security = security; - return NSAPI_ERROR_OK; -} - -nsapi_error_t RDAWiFiInterface::connect(const char *ssid, const char *pass, - nsapi_security_t security, uint8_t channel) -{ - rda_msg msg; - bool find = false; - int i = 0; - rda5981_scan_result bss; - int ret = 0; - - if(wifi_state == WIFI_CONNECTED) { - return NSAPI_ERROR_IS_CONNECTED; - } - - if (ssid == NULL || ssid[0] == 0) { - return NSAPI_ERROR_PARAMETER; - } - - set_credentials(ssid, pass, security); - set_channel(channel); - - init(); - - //reset all scan result to avoid any previous stored SSID/PW/CHANNEL - rda5981_del_scan_all_result(); - rda5981_scan(NULL,0,0); - if(rda5981_check_scan_result_name(ssid) != 0) { - for (i = 0; i< 5; i++) { - rda5981_scan(NULL, 0, 0); - if(rda5981_check_scan_result_name(ssid) == 0) { - find = true; - break; - } - } - } else { - find = true; - } - - if (find == false) { - LWIP_DEBUGF(NETIF_DEBUG,("can not find the ap.\r\n")); - return NSAPI_ERROR_NO_SSID; - } - bss.channel = 15; - rda5981_get_scan_result_name(&bss, ssid); - if ((channel !=0) && (bss.channel != channel)) { - LWIP_DEBUGF(NETIF_DEBUG, ("invalid channel\r\n")); - return NSAPI_ERROR_CONNECTION_TIMEOUT; - } - - memcpy(gssid, ssid, strlen(ssid)); - if (pass[0] != 0) { - memcpy(gpass, pass, strlen(pass)); - } - memset(gbssid, 0, NSAPI_MAC_BYTES); - gssid[strlen(ssid)] = gpass[strlen(pass)] = '\0'; - - msg.type = WLAND_CONNECT; - rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); - ret = rda_sem_wait(wifi_auth_sem, 10000); - if (ret) { - return NSAPI_ERROR_CONNECTION_TIMEOUT; - } - - wifi_state = WIFI_CONNECTED; - - ret = _interface->bringup(_dhcp, - _ip_address[0] ? _ip_address : 0, - _netmask[0] ? _netmask : 0, - _gateway[0] ? _gateway : 0, - DEFAULT_STACK, - _blocking); - LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret)); - - if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) { - ret = NSAPI_ERROR_OK; - } - else if( ret == NSAPI_ERROR_DHCP_FAILURE) { - disconnect(); - } - - return ret; -} - - -nsapi_error_t RDAWiFiInterface::connect() -{ - return connect(_ssid, _pass, _security, _channel); -} - -nsapi_error_t RDAWiFiInterface::disconnect() -{ - rda_msg msg; - - if(wifi_state == WIFI_DISCONNECTED) { - return NSAPI_ERROR_NO_CONNECTION; - } - wifi_state = WIFI_DISCONNECTED; - void* wifi_disconnect_sem = rda_sem_create(0); - msg.type = WLAND_DISCONNECT; - msg.arg1 = (unsigned int)wifi_disconnect_sem; - rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); - rda_sem_wait(wifi_disconnect_sem, osWaitForever); - rda_sem_delete(wifi_disconnect_sem); - if (_interface) { - return _interface->bringdown(); - } - - return NSAPI_ERROR_NO_CONNECTION; -} - -nsapi_error_t RDAWiFiInterface::reconnect() -{ - rda_msg msg; - bool find = false; - int i = 0; - rda5981_scan_result bss; - int ret = 0; - - if (_ssid == NULL || _ssid[0] == 0) { - return NSAPI_ERROR_PARAMETER; - } - - rda5981_del_scan_all_result(); - if(rda5981_check_scan_result_name(_ssid) != 0) { - for (i = 0; i< 5; i++) { - rda5981_scan(NULL, 0, 0); - if(rda5981_check_scan_result_name(_ssid) == 0) { - find = true; - break; - } - } - } else { - find = true; - } - - if (find == false) { - LWIP_DEBUGF(NETIF_DEBUG,"can not find the ap.\r\n"); - return NSAPI_ERROR_CONNECTION_TIMEOUT; - } - bss.channel = 15; - rda5981_get_scan_result_name(&bss, _ssid); - if ((_channel !=0) && (bss.channel != _channel)) { - LWIP_DEBUGF(NETIF_DEBUG, "invalid channel\r\n"); - return NSAPI_ERROR_CONNECTION_TIMEOUT; - } - - memcpy(gssid, _ssid, strlen(_ssid)); - if (_pass[0] != 0) { - memcpy(gpass, _pass, strlen(_pass)); - } - memset(gbssid, 0, NSAPI_MAC_BYTES); - gssid[strlen(_ssid)] = gpass[strlen(_pass)] = '\0'; - - msg.type = WLAND_CONNECT; - rda_mail_put(wland_msgQ, (void*)&msg, osWaitForever); - ret = rda_sem_wait(wifi_auth_sem, 10000); - if (ret) { - return NSAPI_ERROR_CONNECTION_TIMEOUT; - } - - if(_dhcp) { - memset(_ip_address, 0, sizeof(_ip_address)); - memset(_netmask, 0, sizeof(_netmask)); - memset(_gateway, 0, sizeof(_gateway)); - } - - ret = _interface->bringup(_dhcp, - _ip_address[0] ? _ip_address : 0, - _netmask[0] ? _netmask : 0, - _gateway[0] ? _gateway : 0, - DEFAULT_STACK, - _blocking); - LWIP_DEBUGF(NETIF_DEBUG,("Interface bringup up status:%d\r\n",ret)); - - if( ret == NSAPI_ERROR_OK || ret == NSAPI_ERROR_IS_CONNECTED ) { - ret = NSAPI_ERROR_OK; - wifi_state = WIFI_CONNECTED; - } - else if( ret == NSAPI_ERROR_DHCP_FAILURE) { - disconnect(); - } - return ret; -} - - -nsapi_size_or_error_t RDAWiFiInterface::scan(WiFiAccessPoint *res, nsapi_size_t count) -{ - int bss_num = 0, i; - rda5981_scan_result *bss; - nsapi_wifi_ap_t ap; - - init(); - - rda5981_scan(NULL, 0, 0); - bss_num = rda5981_get_scan_num(); - if (count != 0) { - bss_num = (bss_num < count) ? bss_num : count; - } - if (res) { - bss = (rda5981_scan_result *)malloc(bss_num * sizeof(rda5981_scan_result)); - rda5981_get_scan_result(bss, bss_num); - for (i=0; i -#ifdef __cplusplus -extern "C" { -#endif - -extern const unsigned int RDA_FW_INFO_ADDR; -extern const unsigned int RDA_UPGRADE_ADDR; - -/* - * function: start to wirte a partition. this func will erase given flash region - * @addr: partition start address, must be 4k alignment - * @img_len: length of image getted from OTA server, must be 4k alignment - * return: 0:success, else:fail - */ -int rda5981_write_partition_start(unsigned int addr, unsigned int img_len); - -/* - * function: write image to flash, without erase. - * the write region must be inside of the area given by func rda5981_write_partition_start - * the write region must be in order, otherwise the end function will return crc error. - * the maximum length could be write once time is 0x1000 - * @offset: offset from image inital position, must be 1k alignment - * @buf: data to be written - * @len: buffer len, max #0x1000, must be 1k alignment - * return: 0:success, else:fail - */ -int rda5981_write_partition(unsigned int offset, const unsigned char *buf, unsigned int len); - -/* - * function: end of writing partition - * return: 0:crc32 check success, else:fail - */ -int rda5981_write_partition_end(void); - -#ifdef __cplusplus -} -#endif - -#endif /*_RDA5981_OTA_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h deleted file mode 100644 index 0f0f465..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5981_sniffer.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _RDA5981_SNIFFER_H_ -#define _RDA5981_SNIFFER_H_ - -#ifdef __cplusplus -extern "C" { -#endif -#include "wland_types.h" - -/* Enable filtering ACK frames (no support)*/ -//#define RDA_RX_FILTER_DROP_ACK BIT0 - -/* Enable filtering CTS frames (no support)*/ -//#define RDA_RX_FILTER_DROP_CTS BIT1 - -/* Enable filtering RTS frames (no support)*/ -//#define RDA_RX_FILTER_DROP_RTS BIT2 - -/* Enable filtering beacon frames */ -#define RDA_RX_FILTER_DROP_BEACON BIT3 - -/* Enable filtering ATIM frames (no support)*/ -//#define RDA_RX_FILTER_DROP_ATIM BIT4 - -/* Enable filtering CF_END frames (no support)*/ -//#define RDA_RX_FILTER_DROP_CF_END BIT5 - -/* Enable filtering QCF_POLL frames (no support)*/ -//#define RDA_RX_FILTER_DROP_QCF_POLL BIT6 - -/* Filter Management frames which are not directed to current STA */ -#define RDA_RX_FILTER_DROP_ND_MGMT BIT7 - -/* Filter BC/MC MGMT frames belonging to other BSS */ -#define RDA_RX_FILTER_DROP_BC_MC_MGMT_OTHER_BSS BIT8 - -/* Enable filtering of duplicate frames */ -#define RDA_RX_FILTER_DROP_DUPLICATE BIT9 - -/* Enable filtering of frames whose FCS has failed */ -#define RDA_RX_FILTER_DROP_FCS_FAILED BIT10 - -/* Enable filtering of De-authentication frame */ -#define RDA_RX_FILTER_DROP_DEAUTH BIT11 - -/* Filter BA frames which are not received as SIFS response (no support)*/ -//#define RDA_RX_FILTER_DROP_NSIFS_RESP_BA BIT12 - -/* Filter BA frames which are received as SIFS response (no support)*/ -//#define RDA_RX_FILTER_DROP_SIFS_RESP_BA BIT13 - -/* Filter frames which are received in secondary channel (20 MHz PPDU from Secondary channel) */ -#define RDA_RX_FILTER_DROP_SEC_CHANNEL BIT14 - -/* Filter BC/MC DATA frames belonging to other BSS */ -#define RDA_RX_FILTER_DROP_BC_MC_DATA_OTHER_BSS BIT15 - -/* Filter DATA frames not directed to this station */ -#define RDA_RX_FILTER_DROP_ND_DATA BIT16 - -/* Filter Control frames which are not directed to current STA (no support)*/ -//#define RDA_RX_FILTER_DROP_ND_CONTROL BIT17 - -/* Filter Beacon frames (in IBSS mode) which are not used for adoption because the timestamp field is lower than TSF timer */ -#define RDA_RX_FILTER_DROP_IBSS_BEACON BIT18 - -typedef int (*sniffer_handler_t)(unsigned short data_len, void *data); - -int rda5981_enable_sniffer(sniffer_handler_t handler); -int rda5981_disable_sniffer(void); -//don't use this in sniffer callback handler -int rda5981_disable_sniffer_nocallback(void); -///TODO: time is no use anymore -int rda5981_start_sniffer(unsigned char channel, unsigned char to_ds, - unsigned char from_ds, unsigned char mgm_frame, unsigned short time); -int rda5981_stop_sniffer(void); -int wland_sniffer_set_channel(unsigned char channel); -int rda5981_set_filter(unsigned char to_ds, unsigned char from_ds, unsigned int mgm_filter); -int rda5981_sniffer_enable_fcs(void);//for hiflying -#ifdef __cplusplus -} -#endif - -#endif /*_RDA5981_SNIFFER_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h deleted file mode 100644 index 38df3e8..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda5991h_wland.h +++ /dev/null @@ -1,659 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _RDA5991H_WLAND_H_ -#define _RDA5991H_WLAND_H_ - -#include "sys_arch.h" -#include "wland_types.h" - -/* Mbed interface mac address - * if MBED_MAC_ADD_x are zero, interface uid sets mac address, - * otherwise MAC_ADD_x are used. - */ - -extern unsigned char user_mac[6];//not save in flash, need fill before wifi init every time -extern unsigned char gssid[32+1]; -extern unsigned char gpass[64+1]; -extern unsigned char gchannel; -extern unsigned char gbssid[6]; - -extern unsigned char gssid_ap[32+1]; -extern unsigned char gpass_ap[64+1]; -extern unsigned char gchannel_ap; -extern void *wland_msgQ; -extern void *wifi_auth_sem; - -extern u8 sta_state; - -typedef enum { - WLAND_CONNECT, - WLAND_RECONNECT, - WLAND_DISCONNECT, - WLAND_DISCONNECT_ERROR, - WLAND_STARTAP, - WLAND_STOPAP, - WLAND_ADD_AP_GTK, - WLAND_AP_EAPOL_3_OF_4, - WLAND_ADD_AP_PTK, - WLAND_STAJOINED, - WLAND_STAEXITED, - WLAND_STADEAUTH, - WLAND_STADELETETIMER, - WLAND_MAC_CONNECTED, - WLAND_MAC_AP_CONNECTED, - WLAND_ADD_GTK, - WLAND_ADD_PTK, - WLAND_CON_FINISH, - WLAND_AUTO_RATE, - WLAND_ARP_OFFLOAD, - WLAND_SM_START, - WLAND_SM_STOP, - WLAND_WPS_CONNECT, - WLAND_WPS_START, - WLAND_WPS_DISCONNECT, -}WLAND_MSG; - -typedef enum { - MAIN_CONNECT, - MAIN_RECONNECT, - MAIN_DISCONNECT, - MAIN_STOP_AP, -}MAIN_MSG; - -typedef struct { - unsigned int type; - unsigned int arg1; - unsigned int arg2; - unsigned int arg3; -}rda_msg; - - -enum { - D_NONE_LEVEL = 0, - D_ERROR_LEVEL = 1, - D_INFO_LEVEL = 2, - D_DEBUG_LEVEL = 3, -}; - -#define WLAND_DBG_DUMP 0 -#define WPA_DBG_DUMP 0 -#define HUT_DBG_DUMP 0 -#define WLAND_DBG_LEVEL D_NONE_LEVEL -#define WPA_DBG_LEBEL D_NONE_LEVEL -#define WLANDLIB_DBG_LEVEL D_NONE_LEVEL - -#define ETH_ALEN 6 - -//encrypt type -#define ENCRYPT_NONE (0) -#define ENCRYPT_WPA_TKIP BIT0 -#define ENCRYPT_WPA_CCMP BIT1 -#define ENCRYPT_WPA2_TKIP BIT2 -#define ENCRYPT_WPA2_CCMP BIT3 -#define ENCRYPT_WEP BIT4 - -/* r91h driver data structure */ -typedef struct { - struct netif *netif_sta; - struct netif *netif_ap; - sys_thread_t wland_thread; - sys_thread_t maclib_thread; - sys_mbox_t maclib_mbox; - sys_mbox_t wland_mbox; -} rda_enetdata_t; - -__STATIC_INLINE int mac_is_valid(char* mac) -{ - return (mac[0] | mac[1] | mac[2] | mac[3] | mac[4] | mac[5]); -} - - -#ifdef __cplusplus -extern "C" { -#endif - -extern void wland_txip_data(void *data, unsigned int len, int mode); -extern void *wland_get_databuf(void); -extern void wland_sta_init(void); -extern void wland_reg_func(void); -extern void r91h_phy_task(void *data); -extern void wland_task(void *arg); -extern void rda_get_macaddr(u8_t *macaddr, int mode); -extern void rda5981_send_rawdata(char* data, unsigned int len); -extern int rda5981_send_nulldata(int power_save); -extern void rda5981_set_country_code(unsigned char country_code);// 0~china(1-14) 1~NA(1-11) 2~EU(1-13) -extern int rda5981_set_retrans_policy(unsigned char count); -extern int rda5981_set_channel(unsigned char channel); -/* default is 0, receive multicast packet, disable please set 1*/ -extern int rda5981_filter_multicast(unsigned char enable); -/* default is 0, 0 ~ no hidden, 1 ~ hidden zero len, 2 ~ hidden zero contents */ -extern void rda5981_set_AP_hidden_type(unsigned char mode); -extern void rda5981_set_AP_link_num(unsigned char num); -extern char* rda5981_get_ver(void); -extern int rda5981_enter_CE_MODE(unsigned char enable); -/* - * mode 0 - not 11n 1 - 11n - * - * -----------------11n(mode 1)(Mbps)----------------- - * rate HT20 HT40 - * GI(800ns) GI(400ns) GI(800ns) GI(400ns) - * 0 6.5 7.2 13.5 15 - * 1 13 14.2 27 30 - * 2 19.5 21.7 40.5 45 - * 3 26 28.9 54 60 - * 4 39 43.3 81 90 - * 5 52 57.8 108 120 - * 6 58.5 65 121.5 135 - * 7 65 72 135 150 - * - * --------------not 11n(mode 0)(Mbps)----------------- - * rate data rate rate data rate - * 0 autorate 9 9 - * 1 1 12 12 - * 2 2 18 18 - * 5 5.5 24 24 - * 11 11 36 36 - * 6 6 48 48 - * - */ -extern int rda5981_set_data_rate(unsigned char mode, unsigned char rate); -extern void rda5981_set_mode(unsigned char bgn_enable); -extern void rda5981_set_auth_timeout(unsigned char timeout_enable); -typedef struct { - char BSSID[ETH_ALEN]; - char SSID[32+1]; - signed char RSSI; - unsigned char SSID_len; - unsigned char channel; - unsigned char secure_type;//refer #define ENCRYPT_XXX - unsigned char wmm; - unsigned char *ie;//user program couldn't free(ie); - unsigned short capability; - unsigned int ie_length; -} rda5981_scan_result; - -typedef struct { - unsigned char mac[ETH_ALEN]; - unsigned int ip; -} rda5981_apsta_info; - -//scan one or all channel(if channel is 0) once -int rda5981_scan(const char *SSID, const unsigned char SSID_len, const unsigned char channel); -//0 passive mode, 1 active mode, scan time(unit is second) -int rda5981_scan_v2(const char *SSID, const unsigned char SSID_len, const unsigned char channel, const unsigned char mode, \ - const unsigned char scan_time); -int rda5981_get_scan_num(); -int rda5981_get_scan_result(rda5981_scan_result *buf, const unsigned char len); -int rda5981_get_scan_result_index(rda5981_scan_result *buf, const unsigned char index); -int rda5981_get_scan_result_name(rda5981_scan_result *buf, const char *name); -int rda5981_get_scan_result_bssid(rda5981_scan_result *buf, const unsigned char *bssid); -int rda5981_check_scan_result_name(const char *name); -int rda5981_check_scan_result(const char *ssid, const char *bssid, const unsigned channel); -int rda5981_check_scan_result_name_bssid(const unsigned char *name, const unsigned char *bssid); -int rda5981_del_scan_all_result(void); -void rda5981_set_expired_time(unsigned int expired_time); -int rda5981_get_joined_AP(rda5981_scan_result *bss); -s8 rda5981_get_rssi(); -void rda5981_set_main_queue(void* queue); - -void rda5981_set_sta_listen_interval(unsigned char interval); -void rda5981_set_sta_link_loss_time(unsigned char time); -unsigned int rda5981_get_ap_join_info(rda5981_apsta_info *buf, const unsigned char len); -void rda5981_set_AP_white_list(unsigned char flag, unsigned char *mac); -int wland_set_joined_sta_ip(char *mac, unsigned int ip); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_mac_addr(unsigned char *mac_addr); -int rda5981_flash_write_mac_addr(unsigned char *mac_addr); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_uart(void); -int rda5981_flash_read_uart(unsigned int *uart); -int rda5981_flash_write_uart(unsigned int *uart); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_ip_addr(unsigned char *ip_addr, unsigned char *server_addr); -int rda5981_flash_write_ip_addr(unsigned char *ip_add, unsigned char *server_addr); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_dhcp_data(void); -int rda5981_flash_read_dhcp_data(unsigned int *enable, unsigned int *ip, unsigned int *msk, unsigned int *gw); -int rda5981_flash_write_dhcp_data(unsigned int enable, unsigned int ip, unsigned int msk, unsigned int gw); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel); -int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel); -int rda5981_flash_erase_ap_data(void); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, - unsigned int *dhcps, unsigned int *dhcpe); -int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, - unsigned int dhcps, unsigned int dhcpe); -int rda5981_flash_erase_ap_net_data(void); - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_sta_data(char *ssid, char *passwd); -int rda5981_flash_write_sta_data(const char *ssid, const char *passwd); -int rda5981_flash_erase_sta_data(void); - - -/* - * read 3rd parter data length from flash - * return user data length - */ -int rda5981_flash_read_3rdparter_data_length(void); - -/* - * read 3rd parter data from flash - * @buf, buf to store user data - * @buf_len, length of buf - * return user data length - */ -int rda5981_flash_read_3rdparter_data(unsigned char *buf, unsigned int buf_len); - -/* - * write 3rd parter data from flash - * @buf, data to write - * @buf_len, length of buf. - * return 0:ok, else:fail - */ -int rda5981_flash_write_3rdparter_data(const unsigned char *buf, unsigned int buf_len); - -/* - * erase 3rd parter data from flash - * return 0:ok, else:fail - */ -int rda5981_flash_erase_3rdparter_data(void); - -/* - * set flash size - * @size, 1MB:0x100000, 2MB:0x200000, 4MB:0x400000. default size: 1MB - * return 0:ok, else:fail - */ -int rda5981_set_flash_size(const unsigned int size); - -/* - * set userdata location on flash - * @sys_data_addr, data to save system parameter, user can not operate this area directly. - * size:4KB. default location:0x180fb000 - * @user_data_addr, data to save user data. user can save own data in this area - * by @rda5981_flash_read_3rdparter_data - * and @rda5981_flash_write_3rdparter_data - * default location:0x180fc000 - * @user_data_len, user data length, default:4KB - * return 0:ok, else:fail - */ -int rda5981_set_user_data_addr(const unsigned int sys_data_addr, - const unsigned int user_data_addr, const unsigned int user_data_len); - -/* - * function: erase flash - * @addr: mast be 4k alignment - * @len: must be 4k alignment. (package 64KB erase and 4KB erase for different condition automatically) - * return: 0:success, else:fail - */ -int rda5981_erase_flash(unsigned int addr, unsigned int len); - -/* - * function: write flash - * @addr: mast be 256 alignment - * @buf: data to be written, best be 4 alignment - * @len: buffer len, mast be 4 alignment - * return: 0:success, else:fail - */ -int rda5981_write_flash(unsigned int addr, char *buf, unsigned int len); - -/* - * function: read flash to @buf - * @addr: best be 4 alignment - * @buf: best be 4 alignment - * @len: buffer len - * return: 0:success, else:fail - */ -int rda5981_read_flash(unsigned int addr, char *buf, unsigned int len); - -/* - * function: read user data - * @data: data to read - * @len: length of data in byte - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_read_user_data(unsigned char *data, unsigned short len, unsigned int flag); - -/* - * function: write user data - * @data: data to write - * @len: length of data in byte - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_write_user_data(unsigned char *data, unsigned short len, unsigned int flag); - -/* - * function: erase user data - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_erase_user_data(unsigned int flag); - -/* - * function: update tx power from efuse data, for reg 11F and 120 - * return: 0:success, else:fail - */ -int update_tx_power_from_efuse(void); - -/* - * function: update xtal calibration from efuse data, for reg DA - * return: 0:success, else:fail - */ -int update_xtal_cal_from_efuse(void); - -/* - * function: update mac addr from flash data - * return: 0:success, else:fail - */ -int update_mac_addr_from_efuse(void); - -/* - * function: update tx power from flash data, Deprecated version - * return: 0:success, else:fail - */ -int update_tx_power_from_flash(void); - -/* - * function: update tx power from flash data, for reg 8A - * return: 0:success, else:fail - */ -int update_tx_power_rf_from_flash(void); - -/* - * function: update tx power from flash data, for reg 11F and 120 - * return: 0:success, else:fail - */ -int update_tx_power_phy_from_flash(void); - -/* - * function: update xtal calibration from flash data - * return: 0:success, else:fail - */ -int update_xtal_cal_from_flash(void); - -/* - * function: update mac addr from flash data - * return: 0:success, else:fail - */ -int update_mac_addr_from_flash(void); - -/* - * function: write rf reg - * @reg: rf reg data - * @value: rf reg value - * return: 0:success, else:fail - * eg: 0x00DA:xtal calibration - */ -int wland_rf_write(unsigned short reg, unsigned short value); - -/* - * function: write rf reg - * @reg: rf reg data - * @value: rf reg value - * @len : value length - * return: 0:success, else:fail - * eg: 0x008A:tx power rf - */ -int wland_rf_write_all_channels(unsigned short reg, unsigned short *value, unsigned short len); - -/* - * function: read rf reg - * @reg: rf reg data - * @value: rf reg value - * return: 0:success, else:fail - */ -int wland_rf_read(unsigned short reg, unsigned short *value); - -/* - * function: read rf reg - * @reg: rf reg data - * @value: rf reg value - * return: 0:success, else:fail - * eg: 0x008A:tx power rf - */ -int wland_rf_read_all_channels(unsigned short reg, unsigned short *value); - -/* - * function: write phy reg - * @reg: phy reg data - * @value: phy reg value - * return: 0:success, else:fail - */ -int wland_phy_write(unsigned int reg, unsigned int value); - -/* - * function: write phy reg - * @reg: phy reg data - * @value: phy reg value - * @len : value length - * return: 0:success, else:fail - */ -int wland_phy_write_all_channels(unsigned int reg, unsigned int *value, unsigned short len); - -/* - * function: read phy reg - * @reg: phy reg data - * @value: phy reg value - * return: 0:success, else:fail - */ -int wland_phy_read(unsigned int reg, unsigned int *value); - -/* - * function: read phy reg - * @reg: phy reg data - * @value: phy reg value - * return: 0:success, else:fail - */ -int wland_phy_read_all_channels(unsigned int reg, unsigned int *value); - -/* efuse API start */ -/* Efuse CAN ONLY WRITE ONCE! DO NOT CALL THESE API IF YOU DO KNOW WHAT THEY MEANS!!! */ - -/* - * function: read all efuse - * @value: buffer to store efuse data, 28 bytes - * return: 0:success, else:fail - */ -int wland_read_efuse(unsigned char *value); - -/* - * function: read tx power from efuse - * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54). - * return: 0:success, else:fail - */ -int wland_read_tx_power_from_efuse(unsigned char *tx_power); - -/* - * function: read tx power from efuse - * @tx_power: 2 bytes, first is mode g/n(range 0x25~0x54), second is mode b(range 0x15~0x54) - * @len: must be 2 - * return: 0:success, else:fail - */ -int wland_write_tx_power_to_efuse(unsigned char *tx_power, unsigned char len); - -/* - * function: read xtal cal from efuse - * @xtal_cal: 1 byte, maximum 0x7F - * return: 0:success, else:fail - */ -int wland_read_xtal_cal_from_efuse(unsigned char *cal_val); - -/* - * function: write xtal cal to efuse - * @xtal_cal: 1 byte, maximum 0x7F - * @len : must be 1 - * return: 0:success, else:fail - */ -int wland_write_xtal_cal_to_efuse(unsigned char *xtal_cal, unsigned char len); - -/* - * function: write mac to efuse - * @xtal_cal: 6 bytes - * return: 0:success, else:fail - */ -int wland_read_mac_addr_from_efuse(unsigned char *mac_addr); - -/* - * function: write mac to efuse - * @xtal_cal: 6 bytes - * @len : must be 6 - * return: 0:success, else:fail - */ -int wland_write_mac_addr_to_efuse(unsigned char*mac_addr, unsigned char len); -/* efuse API end */ - -/* - * function: start rf test - * @argc: number of argv - * @argv: args for test, 6 elements for tx test, 4 elements for rx test - * @is_tx: 1 for tx test, 0 for rx test - * return: 0:success, else:fail - */ -int wland_start_rf_test(unsigned int argc, unsigned int *argv, unsigned int is_tx); - -/* - * function: stop rx test - * return: 0:success, else:fail - */ -int wland_stop_rx_test(void); - -/* - * function: get rf test result - * @result buffer to store rx result - * return: 0:success, else:fail - */ -int wland_get_rx_result(char *result); - -/* - * function: restart rx test, use last rx test args - * return: 0:success, else:fail - */ -int wland_restart_rx_test(void); - -/* - * function: stop tx test - * return: 0:success, else:fail - */ -int wland_stop_tx_test(void); - -/* - * function: restart tx test, use last tx test args - * return: 0:success, else:fail - */ -int wland_restart_tx_test(void); - -#define RDA5981_FIRMWARE_INFO_ADDR 0x18003000 -/* - * function: reboot to assigned addr (onece). - * reboot to rf test mode, not for OTA - * @firmware_info_addr: firmware info addr, depend on your flash layout - * @reboot_addr: reboot addr, 0x18001000-0x1840000 - * return: 0:success, else:fail - */ -int rda5981_reboot_to_addr(unsigned int firmware_info_addr, unsigned int reboot_addr); - -/* - * function: read reg and corresponding value related to test mode stored in flash - * @reg: reg to read - * @value: buffer to store value - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_read_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); - -/* - * function: write reg and corresponding value related to test mode stored in flash - * @reg: reg to write - * @value: buffer that stores value - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_write_user_data_regs(unsigned char *reg, unsigned char *value, unsigned int flag); - -/* - * function: erase reg and corresponding value related to test mode stored in flash - * @reg: reg to erase - * @flag: user data flag - * return: 0:success, else:fail - */ -int rda5981_erase_user_data_regs(unsigned char *reg, unsigned int flag); - -/* - * function: get flash Manufacturer ID - * @mid: - * return: 0:success, else:fail - */ -int rda5981_flash_get_mid(unsigned char *mid); - -/* - * function: get flash Device ID - * @did: - * return: 0:success, else:fail - */ -int rda5981_flash_get_did(unsigned char *did); - -/* - * function: get flash ID - * @mid: - * return: 0:success, else:fail - */ -int rda5981_flash_get_jdid(unsigned short *jdid); - -/* - * function: read mac reg - * @reg: mac reg data - * @value: mac reg value - * return: 0:success, else:fail - */ -int wland_mac_reg_read(unsigned short reg, unsigned int *value); - -/* - * function: write mac reg - * @reg: mac reg data - * @value: mac reg value - * return: 0:success, else:fail - */ -int wland_mac_reg_write(unsigned short reg, unsigned int value); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h deleted file mode 100644 index 25b80b5..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/rda_sys_wrapper.h +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if 1 -#ifndef _RDA_SYS_WRAPPER_H_ -#define _RDA_SYS_WRAPPER_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Alarm */ -/** - * @brief : get current time in units of micro second - * @param[in] : - * @param[out]: - * @return : return time value with uint32 type - */ -extern unsigned long rda_get_cur_time_ms(void); - -/** - * @brief : create an alarm with given function, return timer handle - * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) - * @param[out]: - * @return : return timer handle, a pointer to the timer structure, non-zero is valid - */ -extern void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode); -extern void * rda_alarm_create(void *func, unsigned int data); - -/** - * @brief : delete an alarm with given handle, then reset the handle - * @param[in] : *handle(pointer to the timer structure) - * @param[out]: **handle(address of the handle variable) - * @return : - */ -extern int rda_alarm_delete(void **handle); - -/** - * @brief : start an alarm, raise a function call after given timeout delay - * @param[in] : handle(pointer to the timer structure)/timeout(micro second) - * @param[out]: - * @return : - */ -extern int rda_alarm_start(void *handle, unsigned int timeout_ms); - -/** - * @brief : stop an alarm, will not raise a function call any more - * @param[in] : handle(pointer to the timer structure) - * @param[out]: - * @return : - */ -extern int rda_alarm_stop(void *handle); - - -/* Semaphore */ -/** - * @brief : create a semaphore - * @param[in] : name and initial valve of semaphore - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern void* rda_sem_create(unsigned int count); - -/** - * @brief : wait a semaphore - * @param[in] : name of semaphore - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_sem_wait(void *sem, unsigned int millisec); - -/** - * @brief : release a semaphore - * @param[in] : name of semaphore - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_sem_release(void *sem); - -/** - * @brief : delete a semaphore - * @param[in] : name of semaphore - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_sem_delete(void *sem); - - -/* Queue */ -/** - * @brief : create a message queue - * @param[in] : size of message queue - * @param[out]: - * @return : return message queue id or NULL if error - */ -extern void* rda_msgQ_create(unsigned int queuesz); - -/** - * @brief : put a message to queue - * @param[in] : message queue id, message value and wait time - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_msg_put(void *msgQId, unsigned int msg, unsigned int millisec); - -/** - * @brief : get a message from queue - * @param[in] : message queue id, message value and wait time - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_msg_get(void *msgQId, unsigned int *value, unsigned int millisec); - -/* Mail */ -/** - * @brief : create a mail - * @param[in] : mail count/size - * @param[out]: - * @return : return mail handle - */ -void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize); - -/** - * @brief : get a msg from mail - * @param[in] : handler name of mail/mail/wait time - * @param[out]: - * @return : return ERR or NO_ERR - */ -int rda_mail_get(void *rdahandle, void *evt, unsigned int wait); - -/** - * @brief : put a msg to mail - * @param[in] : handler of mail/mail/wait time - * @param[out]: - * @return : return ERR or NO_ERR - */ - -int rda_mail_put(void *rdahandle, void *evt, unsigned int wait); - -/* Mutex */ -/** - * @brief : create a mutex - * @param[in] : - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern void* rda_mutex_create(void); - -/** - * @brief : wait a mutex - * @param[in] : id of mutex and wait time - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_mutex_wait(void *rdamutex, unsigned int millisec); - -/** - * @brief : release a mutex - * @param[in] : id of mutex - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_mutex_realease(void *rdamutex); - -/** - * @brief : delete a mutex - * @param[in] : id of mutex - * @param[out]: - * @return : return ERR or NO_ERR - */ -extern int rda_mutex_delete(void *rdamutex); - -/* Thread */ -/** - * @brief : creat a thread - * @param[in] : thread name/thread function/thread fuction argument/stacksize/thread priority - * @param[out]: - * @return : return thread id - */ -void* rda_thread_new(const char *pcName, void (*thread)(void *arg), void *arg, int stacksize, int priority); - -/** - * @brief : delete a thread - * @param[in] : thread id - * @param[out]: - * @return : return ERR or NO_ERR - */ -int rda_thread_delete(void* id); - -/** - * @brief : get current thread id - * @param[in] : - * @param[out]: - * @return : return thread id - */ -void* rda_thread_get_id(void); - -#ifdef __cplusplus -} -#endif - -#endif /* _RDA_SYS_WRAPPER_H_ */ -#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h deleted file mode 100644 index ce418c0..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_dbg.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WLAND_DBG_H_ -#define _WLAND_DBG_H_ -#include -#include "rda5991h_wland.h" -#include "wland_types.h" - -extern int wland_dbg_dump; -extern int wland_dbg_level; - -#define RDA_WLAND_DBG - -#ifdef RDA_WLAND_DBG -#define WLAND_DBG(level, fmt, ...) do {\ - int dbg_level = D_##level##_LEVEL;\ - if((dbg_level <= wland_dbg_level)){\ - printf("%s,"fmt, __func__, ##__VA_ARGS__);\ - } \ - } while (0) - -//if frmae_len is zero, get len from frame header -static inline void wland_dump_frame(const char* msg, u8 *data, u32 frame_len) -{ - - u32 len,i; - - if(wland_dbg_dump == 1) { - if(frame_len != 0) { - len = frame_len; - } else { - len = data[0] | ((data[1]&0x0f) << 8); - } - printf("%s : ",msg); - for(i=0; i= 4) { - wait_busy_down_4(); - } else { - wait_busy_down_2(); - } -} - -static void spi_write_reset(void) -{ - if (rda_ccfg_hwver() >= 4) { - spi_write_reset_4(); - } else { - spi_write_reset_2(); - } -} - -static void spi_wip_reset(void) -{ - if (rda_ccfg_hwver() >= 4) { - spi_wip_reset_4(); - } else { - spi_wip_reset_2(); - } -} - -static inline void spi_flash_enable_cache(void) -{ - unsigned int func = spi_flash_cfg_cache_addr; - if (rda_ccfg_hwver() >= 4) { - func = spi_flash_cfg_cache_addr_4; - } - ((void(*)(void))func)(); -} - -static inline void spi_flash_disable_cache(void) -{ - unsigned int func = spi_flash_disable_cache_addr; - if (rda_ccfg_hwver() >= 4) { - func = spi_flash_disable_cache_addr_4; - } - ((void(*)(void))func)(); -} - -static inline void spi_flash_flush_cache(void) -{ - unsigned int func = spi_flash_flush_cache_addr; - if (rda_ccfg_hwver() >= 4) { - func = spi_flash_flush_cache_addr_4; - } - ((void(*)(void))func)(); -} - -static inline void rda5981_spi_flash_erase_4KB_sector(u32 addr) -{ - unsigned int func = spi_flash_erase_4KB_sector_addr; - if (rda_ccfg_hwver() >= 4) { - func = spi_flash_erase_4KB_sector_addr_4; - } - ((void(*)(u32))func)(addr); -} - -static inline void RDA5991H_ERASE_FLASH(void *addr, u32 len) -{ - unsigned int func = FLASH_ERASE_FUN_ADDR; - if (rda_ccfg_hwver() >= 4) { - func = FLASH_ERASE_FUN_ADDR_4; - } - ((void(*)(void *, u32))func)(addr, len); -} - -static inline void RDA5991H_WRITE_FLASH(u32 addr, u8 *data, u32 len) -{ - unsigned int func = FLASH_WRITE_FUN_ADDR; - if (rda_ccfg_hwver() >= 4) { - func = FLASH_WRITE_FUN_ADDR_4; - } - ((void(*)(u32, u8 *, u32))func)(addr, data, len); -} - -static inline void RDA5991H_READ_FLASH(u32 addr, u8 *buf, u32 len) -{ - unsigned int func = FLASH_READ_FUN_ADDR; - if (rda_ccfg_hwver() >= 4) { - func = FLASH_READ_FUN_ADDR_4; - } - ((void(*)(u32, u8 *, u32))func)(addr, buf, len); -} - -static inline void SPI_FLASH_READ_DATA_FOR_MBED(void *addr, void *buf, u32 len) -{ - unsigned int func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR; - if (rda_ccfg_hwver() >= 4) { - func = SPI_FLASH_READ_DATA_FOR_MBED_ADDR_4; - } - ((void(*)(void *, void *, u32))func)(buf, addr, len); -} - -#endif /*_WLAND_FLASH_H_*/ - diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h deleted file mode 100644 index 40ee40e..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_flash_wp.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WLAND_FLASH_WP_H_ -#define _WLAND_FLASH_WP_H_ - -#ifdef __cplusplus -extern "C" { -#endif -extern void flash_wrtie_protect_all(); -extern void flash_wrtie_protect_none(); -extern void flash_wrtie_protect(unsigned int offset); -extern void rda5981_flash_init(); -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h deleted file mode 100644 index 57b9052..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_ota.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WLAND_OTA_H_ -#define _WLAND_OTA_H_ -#include "wland_types.h" -#include "rda_ccfg_api.h" - -extern u32 flash_size; - -#define CRC32_TABLE_ADDR 0xbb5c -#define CRC32_ADDR 0x8dff//u32 crc32(const u8 *p, size_t len) - -#define CRC32_TABLE_ADDR_4 0xbbd8 -#define CRC32_ADDR_4 0x8e33//u32 crc32(const u8 *p, size_t len) - -static inline unsigned int bootrom_crc32(unsigned char *p, unsigned int len) -{ - unsigned int func = CRC32_ADDR; - if (rda_ccfg_hwver() >= 4) { - func = CRC32_ADDR_4; - } - return ((unsigned int(*)(unsigned char *, unsigned int))func)(p, len); -} - -#endif /*_WLAND_OTA_H_*/ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h deleted file mode 100644 index 6a9ebeb..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_rf.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _WLAND_RF_H_ -#define _WLAND_RF_H_ - -#include "wland_types.h" - -#define WLAND_TXP_NUM 2 -#define WLAND_CHANNEL_NUM 14 -#define WLAND_TX_POWER_PHY_GN_REG 0x11F -#define WLAND_TX_POWER_PHY_B_REG 0x120 -#define WLAND_TX_POWER_RF_REG 0x8A -#define WLAND_XTAL_CAL_REG 0xDA - -#define MAKE_WORD16(lsb, msb) (((u16)(msb) << 8) & 0xFF00) | (lsb) -#define MAKE_WORD32(lsw, msw) (((u32)(msw) << 16) & 0xFFFF0000) | (lsw) - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif - diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h deleted file mode 100644 index 3cb0e7e..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/inc/wland_types.h +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/*****************************************************************************/ -/* */ -/* File Name : wland_types.h */ -/* */ -/* Description : This file contains all the data type definitions for */ -/* MAC implementation. */ -/* */ -/*****************************************************************************/ - -#ifndef WLAND_TYPES_H -#define WLAND_TYPES_H - -/*****************************************************************************/ -/* Constants Definitions */ -/*****************************************************************************/ - -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; -typedef signed char s8; -typedef signed short s16; -typedef signed int s32; -typedef signed long long s64; - -typedef unsigned int size_t; - -/** Indicates Bit Value of BITx */ -#ifndef BIT -#define BIT(x) (1ul << (x)) - -/*****************************************************************************/ -/* Constant Definitions */ -/*****************************************************************************/ - -#define BIT0 (1ul << 0) -#define BIT1 (1ul << 1) -#define BIT2 (1ul << 2) -#define BIT3 (1ul << 3) -#define BIT4 (1ul << 4) -#define BIT5 (1ul << 5) -#define BIT6 (1ul << 6) -#define BIT7 (1ul << 7) -#define BIT8 (1ul << 8) -#define BIT9 (1ul << 9) -#define BIT10 (1ul << 10) -#define BIT11 (1ul << 11) -#define BIT12 (1ul << 12) -#define BIT13 (1ul << 13) -#define BIT14 (1ul << 14) -#define BIT15 (1ul << 15) -#define BIT16 (1ul << 16) -#define BIT17 (1ul << 17) -#define BIT18 (1ul << 18) -#define BIT19 (1ul << 19) -#define BIT20 (1ul << 20) -#define BIT21 (1ul << 21) -#define BIT22 (1ul << 22) -#define BIT23 (1ul << 23) -#define BIT24 (1ul << 24) -#define BIT25 (1ul << 25) -#define BIT26 (1ul << 26) -#define BIT27 (1ul << 27) -#define BIT28 (1ul << 28) -#define BIT29 (1ul << 29) -#define BIT30 (1ul << 30) -#define BIT31 (1ul << 31) -#endif - -#endif /* WLAND_TYPES_H */ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt deleted file mode 100644 index 24e2529..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/LICENSE-permissive-binary-license-1.0.txt +++ /dev/null @@ -1,49 +0,0 @@ -Permissive Binary License - -Version 1.0, January 2019 - -Redistribution. Redistribution and use in binary form, without -modification, are permitted provided that the following conditions are -met: - -1) Redistributions must reproduce the above copyright notice and the - following disclaimer in the documentation and/or other materials - provided with the distribution. - -2) Unless to the extent explicitly permitted by law, no reverse - engineering, decompilation, or disassembly of this software is - permitted. - -3) Redistribution as part of a software development kit must include the - accompanying file named �DEPENDENCIES� and any dependencies listed in - that file. - -4) Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -Limited patent license. The copyright holders (and contributors) grant a -worldwide, non-exclusive, no-charge, royalty-free patent license to -make, have made, use, offer to sell, sell, import, and otherwise -transfer this software, where such license applies only to those patent -claims licensable by the copyright holders (and contributors) that are -necessarily infringed by this software. This patent license shall not -apply to any combinations that include this software. No hardware is -licensed hereunder. - -If you institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the software -itself infringes your patent(s), then your rights granted under this -license shall terminate as of the date such litigation is filed. - -DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT -NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md deleted file mode 100644 index 5df1aa3..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/README.md +++ /dev/null @@ -1,7 +0,0 @@ -This directory tree contains binaries build from RDA SDK modified for Mbed OS and released under Permissive Binary License. - -libhal files in the subfolders are generated with toolchains: - -Arm Compiler 5 - version 5.06u6 -GNU Arm Embedded - version 6.3.1 -IAR EWARM - version 8.32.2.178 \ No newline at end of file diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar deleted file mode 100644 index 907d766..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_ARM_STD/libwifi_sta_ap.ar +++ /dev/null Binary files differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a deleted file mode 100644 index 4d2ed20..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_GCC_ARM/libwifi_sta_ap.a +++ /dev/null Binary files differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a deleted file mode 100644 index a98ce3c..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/lib/TOOLCHAIN_IAR/libwifi_sta_ap.a +++ /dev/null Binary files differ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c deleted file mode 100644 index 251133e..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/maclib_task.c +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/****************************************************************************** - * @file : maclib_task.c - * @brief : WiFi MACLib task source file - * @version: V1.0 - * @date : 6. May 2017 - * - * @note - * - ******************************************************************************/ -#include -#include -#include - -#include "mbed_interface.h" -#include "cmsis_os.h" -#include "csl_mbed.h" -#include "maclib_task.h" -#include "rda5991h_wland.h" - -#include "lwip/pbuf.h" -#include "lwip/sys.h" - -/** - * Macros - */ -#define MACLIB_TASK_DEBUG (0) - -/** - * Variables - */ -static int maclib_task_run = 0; -static void* maclib_mbox; -static int g_event_num = 0; -static int g_event_proc_done = 1; -static sys_sem_t g_maclib_sem_sleep; -static int g_maclib_sleep_flag = 0; - -extern maclib_func_t *maclib_func_p; - -extern void rda_critical_sec_start(void); -extern void rda_critical_sec_end(void); -extern void wland_set_sta_sleep(unsigned char is_sleep); -/** - * Functions - */ -/* maybe called in isr, should not use "printf", "malloc" */ -void mbed_event_handle_cb(unsigned int event) -{ - static unsigned int sec_cnt = 0; - MACLIB_EVENT_HANDLE_T type = (MACLIB_EVENT_HANDLE_T)event; - if ((maclib_task_run == 0) && (MACLIB_EVENT_CLEANUP != type)) { - mbed_error_printf("evntHndlCb_nulldata\r\n"); - return; - } - switch(type) { - case MACLIB_EVENT_PEND: - rda_critical_sec_start(); - g_event_num++; - if((1 == g_event_num) && (1 == g_event_proc_done)) { - maclib_msg_t msg; -#if MACLIB_TASK_DEBUG - mbed_error_printf("#1-1,%d(%08X)\r\n", g_event_num, __get_xPSR()); -#endif - msg.type = MACLIB_MSG_EVNT_HNDL; - msg.msg = NULL; - rda_mail_put(maclib_mbox, (void*)&msg, 0); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#1-2\r\n"); -#endif - } - rda_critical_sec_end(); - break; - case MACLIB_EVENT_PROCESS: -#if 1 - rda_critical_sec_start(); - g_event_num--; - if(0 > g_event_num) { - mbed_error_printf("event handle err\r\n"); - g_event_num = 0; - } - rda_critical_sec_end(); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#3,%d\r\n",g_event_num); -#endif -#endif - break; - case MACLIB_EVENT_CLEANUP: -#if MACLIB_TASK_DEBUG - mbed_error_printf("event cleanup\r\n"); -#endif - rda_critical_sec_start(); - g_event_num = 0; - rda_critical_sec_end(); - break; - default: - break; - } -} - -void mbed_mltask_sleep_cb(void) -{ - g_maclib_sleep_flag = 1; - sys_arch_sem_wait(&g_maclib_sem_sleep, 0); -} - -void mbed_mltask_wakeup_cb(void) -{ - rda_critical_sec_start(); - if (1 == g_maclib_sleep_flag) { - g_maclib_sleep_flag = 0; - sys_sem_signal(&g_maclib_sem_sleep); - } - rda_critical_sec_end(); -} - -void maclib_check_status(void) -{ - rda_critical_sec_start(); - if (1 == g_maclib_sleep_flag) { - if(*((unsigned int *)0x40020580U) & (0x01UL << 2)) { - mbed_mltask_wakeup_cb(); - } - } - rda_critical_sec_end(); -} - -int maclib_is_sleep_allowed(void) -{ - return g_maclib_sleep_flag; -} - -void maclib_task(void *pvParameters) -{ - int ret; -#if 0 - sleep_entry_t maclib_sleep_entry = { - wland_set_sta_sleep, - maclib_is_sleep_allowed, - maclib_check_status - }; -#endif - sys_sem_new(&g_maclib_sem_sleep, 0); - //sleep_entry_register(&maclib_sleep_entry); - - maclib_mbox = (void *)rda_mail_create(8, sizeof(maclib_msg_t));//ret = sys_mbox_new(&(maclib_mbox), 8); - if(NULL == maclib_mbox) { - mbed_error_printf("msgbox init err!\r\n"); - goto mac_lib_err; - } -#if MACLIB_TASK_DEBUG - LWIP_DEBUGF(NETIF_DEBUG,"#mbox new\r\n"); -#endif - maclib_task_run = 1; - while(1) { - maclib_msg_t msg; - osStatus_t status = rda_mail_get(maclib_mbox, (void *)&msg, osWaitForever); - if(osOK != status) { - mbed_error_printf("ml_task: invalid msg ret=%08X\r\n", status); - continue; - } - switch(msg.type) { - case MACLIB_MSG_EVNT_HNDL: { - rda_critical_sec_start(); - g_event_proc_done = 0; - rda_critical_sec_end(); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#get event %d\r\n", g_event_num); -#endif - maclib_func_p->ml_tasklet(); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#5\r\n"); -#endif - rda_critical_sec_start(); -#if 0 - g_event_num--; - if(0 > g_event_num) { - mbed_error_printf("event handle err\r\n"); - } else -#endif - g_event_proc_done = 1; - if(0 < g_event_num) { -#if MACLIB_TASK_DEBUG - mbed_error_printf("#2-1\r\n"); -#endif - rda_mail_put(maclib_mbox, (void*)&msg, 0); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#2-2\r\n"); -#endif - } - rda_critical_sec_end(); -#if MACLIB_TASK_DEBUG - mbed_error_printf("#pDone\r\n"); -#endif - break; - } - default: - break; - } -#if MACLIB_TASK_DEBUG - mbed_error_printf("#4\r\n"); -#endif - } - -mac_lib_err: - LWIP_DEBUGF(NETIF_DEBUG,"MACLib exit!\r\n"); - osDelay(osWaitForever); -} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c deleted file mode 100644 index d51064e..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda5991h_wland.c +++ /dev/null @@ -1,530 +0,0 @@ -/* Copyright (c) 2019 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/****************************************************************************** - * @file rda5991h_wland.c - * @brief RDA5991H wlan driver for LWIP - * @version: V1.0 - * @date: 25. July 2016 - * - * @note - * Copyright (C) 2009 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#include "lwip/opt.h" -#include "lwip/sys.h" -#include "lwip/def.h" -#include "lwip/mem.h" -#include "lwip/pbuf.h" -#include "lwip/stats.h" -#include "lwip/snmp.h" -#include "lwip/tcpip.h" -#include "netif/etharp.h" -#include "sys_arch.h" -#include "rda5991h_wland.h" -#include "cmsis.h" -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -#include "entropy_poll.h" -#else -#include "trng_api.h" -#endif -#include "gpio_api.h" -#include "gpio_irq_api.h" -#include "maclib_task.h" -#include "rda_sys_wrapper.h" -#include -#include -#include -#include - -/* Global variables */ -rda_enetdata_t r91h_wifidata; - -int wland_dbg_dump = WLAND_DBG_DUMP; -int wland_dbg_level = WLAND_DBG_LEVEL; -int wpa_dbg_dump = WPA_DBG_DUMP; -int wpa_dbg_level = WPA_DBG_LEBEL; -int wlandlib_dbg_level = WLANDLIB_DBG_LEVEL; -int hut_dbg_dump = HUT_DBG_DUMP; - -//#define CONFIG_DISABLE_ALL_INT -#define CRI_SEC_START_PRI_LEVEL 0xF8 -#define CRI_SEC_END_PRI_LEVEL 0x00 -static unsigned int g_critical_sec_counter = 0U; -#if defined(CONFIG_DISABLE_ALL_INT) -static unsigned int g_critical_ctxt_saved = 0U; -#endif /* CONFIG_DISABLE_ALL_INT */ -void *packet_rx_queue; - -/* Function statements */ -void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx); -void mbed_mac_address(char *mac); - -/** \brief Driver transmit and receive thread priorities - * - * Thread priorities for receive thread and TX cleanup thread. Alter - * to prioritize receive or transmit bandwidth. In a heavily loaded - * system or with LEIP_DEBUG enabled, the priorities might be better - * the same. */ -#define RX_PRIORITY (osPriorityNormal) -#define TX_PRIORITY (osPriorityNormal) -#define PHY_PRIORITY (osPriorityNormal) - -void rda_netif_down(int netif) -{ - if (netif == 0) { - netif_set_down(r91h_wifidata.netif_sta); - } else { - netif_set_down(r91h_wifidata.netif_ap); - } -} - -void rda_netif_link_down(int netif) -{ - rda_msg msg; - msg.type = 1; - msg.arg1 = 0; - rda_mail_put(packet_rx_queue, (void*)&msg, 0); -} - -void rda_netif_up(int netif) -{ - if (netif == 0) { - netif_set_up(r91h_wifidata.netif_sta); - } else { - netif_set_up(r91h_wifidata.netif_ap); - } -} - -void rda_netif_link_up(int netif) -{ - rda_msg msg; - msg.type = 1; - msg.arg1 = 1; - rda_mail_put(packet_rx_queue, (void*)&msg, 0); - return; -} - -void rda_netif_input(u8_t *data, u32_t len, int idx, int netif) -{ - if (netif == 0) { - r91h_wifiif_input(r91h_wifidata.netif_sta, data, len, idx++); - } else { - r91h_wifiif_input(r91h_wifidata.netif_ap, data, len, idx++); - } -} - -void rda_get_macaddr(u8_t *macaddr, int mode) -{ - mbed_mac_address((char *)macaddr); - if (mode == 1) { - if(macaddr[0] & 0x04) { - macaddr[0] &= 0xFB; - } else { - macaddr[0] |= 0x04; - } - } - return; -} - -void rda_critical_sec_start(void) -{ - if (__get_IPSR() == 0U) { - if (0U == g_critical_sec_counter) { -#if defined(CONFIG_DISABLE_ALL_INT) - g_critical_ctxt_saved = __disable_irq(); -#else /* CONFIG_DISABLE_ALL_INT */ - __set_BASEPRI(CRI_SEC_START_PRI_LEVEL); -#endif /* CONFIG_DISABLE_ALL_INT */ - } - g_critical_sec_counter++; - } -} - -void rda_critical_sec_end(void) -{ - if (__get_IPSR() == 0U) { - g_critical_sec_counter--; - if (0U == g_critical_sec_counter) { -#if defined(CONFIG_DISABLE_ALL_INT) - __set_PRIMASK(g_critical_ctxt_saved); -#else /* CONFIG_DISABLE_ALL_INT */ - __set_BASEPRI(CRI_SEC_END_PRI_LEVEL); -#endif /* CONFIG_DISABLE_ALL_INT */ - } - } -} - -unsigned int rda_critical_sec_counter_get(void) -{ - if (__get_IPSR() == 0U) { - return g_critical_sec_counter; - } else { - return 0xFFFFFFFF; - } -} - -void rda_critical_sec_start_resume(unsigned int cnt) -{ - unsigned int i = 0; - for(i=0; inext) { - /* Read enough bytes to fill this pbuf in the chain. The - * available data in the pbuf is given by the q->len - * variable. - * This does not necessarily have to be a memcpy, you can also preallocate - * pbufs for a DMA-enabled MAC and after receiving truncate it to the - * actually received size. In this case, ensure the tot_len member of the - * pbuf is the sum of the chained pbuf len members. - */ - /* load rx data from 96 to local mem_pool */ - MEMCPY(q->payload, &data[index], q->len); - index += q->len; - - if (index >= len) { - break; - } - } - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.recv); - } else { - /* Drop this packet */ - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); - LINK_STATS_INC(link.memerr); - LINK_STATS_INC(link.drop); - - return NULL; - } - - return p; -} - -/** \brief Attempt to read a packet from the EMAC interface. - * - * \param[in] netif the lwip network interface structure - * \param[in] idx index of packet to be read - */ -void r91h_wifiif_input(struct netif *netif, u8_t *data, u32_t len, int idx) -{ - rda_msg msg; - msg.type = 0; - msg.arg1 = (int)data; - msg.arg2 = len; - rda_mail_put(packet_rx_queue, (void*)&msg, 0); - return; -} - -/** \brief Low level init of the MAC and PHY. - * - * \param[in] netif Pointer to LWIP netif structure - */ - -static err_t low_level_init(struct netif *netif) -{ - static int init_flag = 0; - if (init_flag == 0) { - wland_reg_func(); - init_flag = 1; - } - return ERR_OK; -} - -/** - * This function is the ethernet packet send function. It calls - * etharp_output after checking link status. - * - * \param[in] netif the lwip network interface structure for this enetif - * \param[in] q Pointer to pbug to send - * \param[in] ipaddr IP address - * \return ERR_OK or error code - */ -err_t rda91h_etharp_output(struct netif *netif, struct pbuf *q, const ip_addr_t *ipaddr) -{ - /* Only send packet is link is up */ - if (netif->flags & NETIF_FLAG_LINK_UP) - return etharp_output(netif, q, ipaddr); - - return ERR_CONN; -} - -/** \brief Low level output of a packet. Never call this from an - * interrupt context, as it may block until TX descriptors - * become available. - * - * \param[in] netif the lwip network interface structure for this netif - * \param[in] p the MAC packet to send (e.g. IP packet including MAC addresses and type) - * \return ERR_OK if the packet could be sent or an err_t value if the packet couldn't be sent - */ -static err_t rda91h_low_level_output(struct netif *netif, struct pbuf *p) -{ - struct pbuf *q; - - /* rda5996 initiate transfer */ - u32_t actual_txlen = 0; - u8_t **data; - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); - -#if ETH_PAD_SIZE - pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ -#endif - - data = (void*)wland_get_databuf(); - - if(data == NULL){ - LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); - return ERR_BUF; - } - - for(q = p; q != NULL; q = q->next) - { - /* Send the data from the pbuf to the interface, one pbuf at a - time. The size of the data in each pbuf is kept in the ->len - variable. */ - MEMCPY(&((*data)[actual_txlen+2]), q->payload, q->len);//reserve wid header length - actual_txlen += q->len; - if(actual_txlen > 1514 || actual_txlen > p->tot_len) - { - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", - actual_txlen, p->tot_len)); - return ERR_BUF; - } - } - - /* Signal rda5996 that packet should be sent */ - if(actual_txlen == p->tot_len) - { - if(netif->name[0] == 's' && netif->name[1] == 't') { - wland_txip_data((void*)data, actual_txlen, 0); - } else if(netif->name[0] == 'a' && netif->name[1] == 'p') { - wland_txip_data((void*)data, actual_txlen, 1); - } - -#if ETH_PAD_SIZE - pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ -#endif - - LINK_STATS_INC(link.xmit); - - return ERR_OK; - } - - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", - actual_txlen, p->tot_len)); - - - return ERR_BUF; -} - -/** - * Should be called at the beginning of the program to set up the - * network interface. - * - * This function should be passed as a parameter to netif_add(). - * - * @param[in] netif the lwip network interface structure for this netif - * @return ERR_OK if the loopif is initialized - * ERR_MEM if private data couldn't be allocated - * any other err_t on error - */ -err_t wifi_arch_enetif_init(struct netif *netif) -{ - err_t err; - static int thread_init_flag = 0; - LWIP_ASSERT("netif != NULL", (netif != NULL)); - - if (*((int *)netif->state) == 0) { - r91h_wifidata.netif_sta = netif; - netif->name[0] = 's'; - netif->name[1] = 't'; -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - if(netif->hostname == NULL) - netif->hostname = "lwipr91h_sta"; -#endif /* LWIP_NETIF_HOSTNAME */ - rda_get_macaddr((u8_t *)(netif->hwaddr), 0); - } else if(*((int *)netif->state) == 1) { - r91h_wifidata.netif_ap = netif; - netif->name[0] = 'a'; - netif->name[1] = 'p'; -#if LWIP_NETIF_HOSTNAME - /* Initialize interface hostname */ - if(netif->hostname == NULL) - netif->hostname = "lwipr91h_ap"; -#endif /* LWIP_NETIF_HOSTNAME */ - rda_get_macaddr((u8_t *)(netif->hwaddr), 1); - } - - netif->hwaddr_len = ETHARP_HWADDR_LEN; - - /* maximum transfer unit */ - netif->mtu = 1500; - - /* device capabilities */ - // TODOETH: check if the flags are correct below - netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP; - - /* Initialize the hardware */ - netif->state = &r91h_wifidata; - err = low_level_init(netif); - if (err != ERR_OK) - return err; - - netif->output = rda91h_etharp_output; - netif->linkoutput = rda91h_low_level_output; - if(thread_init_flag == 0){ - /* PHY monitoring task */ - sys_thread_new("maclib_thread", maclib_task, netif->state, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); - sys_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - thread_init_flag = 1; - } - return ERR_OK; -} - -unsigned char rda_mac_addr[6] = "\0"; -static int is_available_mac_addr(unsigned char *mac_addr) -{ - if (mac_addr[0]==0 && mac_addr[1]==0 && mac_addr[2]==0 && - mac_addr[3]==0 && mac_addr[4]==0 && mac_addr[5]==0) - return 0; - if (mac_addr[0]&0x1) - return 0; - return 1; -} -static void rda_get_macaddr_from_flash(unsigned char *macaddr) -{ - int ret; - if (!mac_is_valid((char *)rda_mac_addr)) { - ret = rda5981_flash_read_mac_addr(rda_mac_addr); - if ((ret!=0) || (is_available_mac_addr(rda_mac_addr)==0)) { -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - unsigned int out_len; - ret = mbedtls_hardware_poll(NULL, rda_mac_addr, 6, &out_len); - if (6 != out_len) { - LWIP_DEBUGF(NETIF_DEBUG, ("out_len err:%d\n", out_len)); - } -#else - ret = rda_trng_get_bytes(rda_mac_addr, 6); -#endif - rda_mac_addr[0] &= 0xfe; /* clear multicast bit */ - rda_mac_addr[0] |= 0x02; /* set local assignment bit (IEEE802) */ - rda5981_flash_write_mac_addr(rda_mac_addr); - } - } - memcpy(macaddr, rda_mac_addr, 6); -} -void mbed_mac_address(char *mac) -{ - mac[0] = 0xD6; - mac[1] = 0x71; - mac[2] = 0x36; - mac[3] = 0x60; - mac[4] = 0xD8; -#if !MBED_CONF_APP_ECHO_SERVER - mac[5] = 0xF4; -#else - mac[5] = 0xF3; -#endif - return; -} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c deleted file mode 100644 index 07781ff..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/rda_sys_wrapper.c +++ /dev/null @@ -1,453 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if 1 -#include "sys_arch.h" -#include "cmsis_os.h" -#include "cmsis_os2.h" -#include "lwip/sys.h" -#include "rtx_lib.h" - -#include -#include -#include "mbed_assert.h" -#define NO_ERR 0 -#define ERR -1 - -//#define RDA_SYS_DEBUG -#ifdef RDA_SYS_DEBUG -#define RDA_SYS_PRINT(fmt, ...) do {\ - printf(fmt, ##__VA_ARGS__);\ - } while (0) -#else -#define RDA_SYS_PRINT(fmt, ...) -#endif - - -/* Alarm */ -// Timer definitions -#define osTimerInvalid 0 -#define osTimerStopped 1 -#define osTimerRunning 2 -#if 0 -// Timer structures, same as os_timer_cb(rt_CMSIS.c) -typedef struct rda_ostmr_cb { - struct rda_ostmr_cb *next; // Pointer to next active Timer - uint8_t state; // Timer State - uint8_t type; // Timer Type (Periodic/One-shot) - uint16_t reserved; // Reserved - uint32_t tcnt; // Timer Delay Count - uint32_t icnt; // Timer Initial Count - void *arg; // Timer Function Argument - const osTimerDef_t *timer; // Pointer to Timer definition -} rda_ostmr_cb_t; -#endif -//#define USING_STDLIB - -#if !defined(USING_STDLIB) -typedef struct rda_tmr_node { - mbed_rtos_storage_timer_t _obj_mem; -} rda_tmr_node_t; - -typedef struct rda_tmr_ctrl { - unsigned char *buff; - unsigned char *state; - unsigned char max_node_num; - unsigned char node_size; - unsigned char node_cntr; - unsigned char last_freed_node_idx; -} rda_tmr_ctrl_t; - -#define MAX_ALARM_NUM (28) -#define WORD_ALIGN(n) (((n) + 0x03UL) & ~0x03UL) -#define MAX_ALARM_STAT_SIZE WORD_ALIGN(MAX_ALARM_NUM >> 3) -#define MAX_ALARM_MEM_SIZE (MAX_ALARM_NUM * WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)) + MAX_ALARM_STAT_SIZE) - -unsigned long g_alarm_buf[WORD_ALIGN(MAX_ALARM_MEM_SIZE) >> 2] = {0}; -rda_tmr_ctrl_t g_alarm_ctrl = { - (unsigned char *)g_alarm_buf + MAX_ALARM_STAT_SIZE, - (unsigned char *)g_alarm_buf, - MAX_ALARM_NUM, - WORD_ALIGN(sizeof(mbed_rtos_storage_timer_t)), - 0U, - 0U -}; - -__STATIC_INLINE unsigned char get_node_state(unsigned char *buf, unsigned char idx) -{ - unsigned char state, ofst; - ofst = (idx & 0x07U); - buf += (idx >> 3); - state = (*buf >> ofst) & 0x01U; - return state; -} - -__STATIC_INLINE void set_node_state(unsigned char *buf, unsigned char idx, unsigned char state) -{ - unsigned char ofst, tmp; - ofst = (idx & 0x07U); - buf += (idx >> 3); - tmp = *buf & (~(0x01U << ofst)); - *buf = tmp | (((state & 0x01U) << ofst)); -} - -static rda_tmr_node_t *get_tmr_node(void) -{ - rda_tmr_node_t *node = NULL; - unsigned char idx = g_alarm_ctrl.last_freed_node_idx; - if ((idx < g_alarm_ctrl.max_node_num) && (0U == get_node_state(g_alarm_ctrl.state, idx))) { - set_node_state(g_alarm_ctrl.state, idx, 1U); - node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); - g_alarm_ctrl.node_cntr++; - } else { - for (idx = 0U; idx < g_alarm_ctrl.max_node_num; idx++) { - if(0U == get_node_state(g_alarm_ctrl.state, idx)) { - set_node_state(g_alarm_ctrl.state, idx, 1U); - node = (rda_tmr_node_t *)(g_alarm_ctrl.buff + idx * g_alarm_ctrl.node_size); - g_alarm_ctrl.node_cntr++; - break; - } - } - } - return node; -} - -static void put_tmr_node(rda_tmr_node_t *node) -{ - unsigned char *node_buf = (unsigned char *)node; - unsigned char idx = (node_buf - g_alarm_ctrl.buff) / g_alarm_ctrl.node_size; - if ((node_buf > g_alarm_ctrl.buff) && (idx < g_alarm_ctrl.max_node_num) && - (1U == get_node_state(g_alarm_ctrl.state, idx))) { - set_node_state(g_alarm_ctrl.state, idx, 0U); - g_alarm_ctrl.node_cntr--; - g_alarm_ctrl.last_freed_node_idx = idx; - } -} -#endif /* !USING_STDLIB */ - -/** - * @brief : get current time in units of micro second - * @param[in] : - * @param[out]: - * @return : return time value with uint32 type - */ -unsigned long rda_get_cur_time_ms(void) -{ - return sys_now(); -} - -/** - * @brief : create an alarm with given function, return timer handle - * @param[in] : func(callback)/data(pass to func)/mode(once or periodic) - * @param[out]: - * @return : return timer handle, a pointer to the timer structure, non-zero is valid - */ -void * rda_alarm_create_v2(void *func, unsigned int data, unsigned int mode) -{ - osTimerId_t handle; - mbed_rtos_storage_timer_t* _obj_mem = NULL; - MBED_ASSERT(func != NULL); - osTimerAttr_t attr = { 0 }; -#if defined(USING_STDLIB) - _obj_mem = (mbed_rtos_storage_timer_t*)malloc(sizeof(mbed_rtos_storage_timer_t)); -#else /* USING_STDLIB */ - _obj_mem = (mbed_rtos_storage_timer_t*)get_tmr_node(); -#endif /* USING_STDLIB */ - MBED_ASSERT(_obj_mem != NULL); - memset(_obj_mem, 0, sizeof(_obj_mem)); - attr.cb_mem = _obj_mem; - attr.cb_size = sizeof(mbed_rtos_storage_timer_t); - //printf("hehehehe fun %p\r\n", func); - handle = osTimerNew((osTimerFunc_t)func, mode, (void *)data, &attr); - //printf("time cb %p handle %p\r\n", _obj_mem, handle); - MBED_ASSERT(handle != NULL); - return handle; -} - -void * rda_alarm_create(void *func, unsigned int data) -{ - return rda_alarm_create_v2(func, data, osTimerOnce); -} - -/** - * @brief : delete an alarm with given handle, then reset the handle - * @param[in] : *handle(pointer to the timer structure) - * @param[out]: **handle(address of the handle variable) - * @return : - */ -int rda_alarm_delete(void **handle) -{ - if (NULL != *handle) { - osTimerId timer_id = (osTimerId)(*handle); - osStatus retval = osTimerDelete(timer_id); - if (osOK == retval) { -#if defined(USING_STDLIB) - free(timer_id); -#else /* USING_STDLIB */ - put_tmr_node((rda_tmr_node_t *)timer_id); -#endif /* USING_STDLIB */ - *handle = NULL; - } else { - RDA_SYS_PRINT("Delete alarm error: %d\r\n", retval); - return ERR; - } - return NO_ERR; - } - return ERR; -} - -/** - * @brief : start an alarm, raise a function call after given timeout delay - * @param[in] : handle(pointer to the timer structure)/timeout(micro second) - * @param[out]: - * @return : - */ -int rda_alarm_start(void *handle, unsigned int timeout_ms) -{ - if (NULL != handle) { - osTimerId timer_id = (osTimerId)handle; - osStatus retval = osTimerStart(timer_id, (uint32_t)timeout_ms); - if (osOK != retval) { - RDA_SYS_PRINT("Start alarm error: %d\r\n", retval); - return ERR; - } - return NO_ERR; - } - return ERR; -} - -/** - * @brief : stop an alarm, will not raise a function call any more - * @param[in] : handle(pointer to the timer structure) - * @param[out]: - * @return : - */ -int rda_alarm_stop(void *handle) -{ - if (NULL != handle) { - osTimerId timer_id = (osTimerId)handle; - os_timer_t *timer = osRtxTimerId(timer_id); - if(timer->state == osRtxTimerRunning){ - osStatus retval = osTimerStop(timer_id); - if(osOK != retval) { - RDA_SYS_PRINT("Stop alarm error: %d\r\n", retval); - return ERR; - } - } - return NO_ERR; - } - return ERR; -} - - - -/* Semaphore */ -void* rda_sem_create(unsigned int count) -{ - osSemaphoreId_t sem; - mbed_rtos_storage_semaphore_t *_obj_mem = (mbed_rtos_storage_semaphore_t*)malloc(sizeof(mbed_rtos_storage_semaphore_t)); - osSemaphoreAttr_t attr = { 0 }; - attr.name = "rda_unnamed_sem"; - attr.cb_mem = _obj_mem; - attr.cb_size = sizeof(mbed_rtos_storage_semaphore_t); - sem = osSemaphoreNew(1, count, &attr); - MBED_ASSERT(sem != NULL); - - return (void*)sem; -} - -int rda_sem_wait(void* sem, unsigned int millisec) -{ - int res; - - res = osSemaphoreWait(sem, millisec); - if (res > 0) { - return NO_ERR; - } else { - RDA_SYS_PRINT("rda_sem_wait error %d\r\n", res); - return ERR; - } -} - -int rda_sem_release(void *sem) -{ - int res; - - res = osSemaphoreRelease(sem); - if (res == 0) { - return NO_ERR; - } else { - RDA_SYS_PRINT("rda_sem_release error %d\r\n", res); - return ERR; - } -} - -int rda_sem_delete(void *sem) -{ - int res; - - res = osSemaphoreDelete(sem); - free(sem); - if (res == 0) { - return NO_ERR; - } else { - RDA_SYS_PRINT("rda_sem_delete error %d\r\n", res); - return ERR; - } -} - -/* Mail */ -void* rda_mail_create(unsigned int msgcnt, unsigned int msgsize) -{ - unsigned int mq_size = msgcnt * (msgsize + sizeof(os_message_t)); - osMessageQueueId_t msgq; - mbed_rtos_storage_msg_queue_t *_obj_mem = (mbed_rtos_storage_msg_queue_t*)malloc(sizeof(mbed_rtos_storage_msg_queue_t)); - MBED_ASSERT(_obj_mem != NULL); - memset(_obj_mem, 0, sizeof(mbed_rtos_storage_msg_queue_t)); - void *_mq_mem = (void *)malloc(mq_size); - MBED_ASSERT(_mq_mem != NULL); - memset(_mq_mem, 0, mq_size); - osMessageQueueAttr_t attr = { 0 }; - attr.name = "rda_unnamed_message_queue"; - attr.cb_mem = _obj_mem; - attr.cb_size = sizeof(mbed_rtos_storage_msg_queue_t); - attr.mq_mem = _mq_mem; - attr.mq_size = mq_size; - msgq = osMessageQueueNew(msgcnt, msgsize, &attr); - MBED_ASSERT(msgq != NULL); - - return (void*)msgq; -} - -int rda_mail_get(void *msgq, void *msg, unsigned int wait) -{ - int ret; - ret = osMessageQueueGet(msgq, msg, 0, wait); - return ret; -} - -int rda_mail_put(void *msgq, void *msg, unsigned int wait) -{ - int ret; - ret = osMessageQueuePut(msgq, msg, 0, wait); - return ret; -} - -/* Mutex */ -void* rda_mutex_create(void) -{ - osMutexId_t rdamutex; - osMutexAttr_t attr = { 0 }; - mbed_rtos_storage_mutex_t *_obj_mem = (mbed_rtos_storage_mutex_t *)malloc(sizeof(mbed_rtos_storage_mutex_t)); - memset(_obj_mem, 0, sizeof(mbed_rtos_storage_mutex_t)); - attr.name = "rda_unnamed_mutex"; - attr.cb_mem = _obj_mem; - attr.cb_size = sizeof(mbed_rtos_storage_mutex_t); - attr.attr_bits = osMutexRecursive | osMutexPrioInherit | osMutexRobust; - rdamutex = osMutexNew(&attr); - MBED_ASSERT(rdamutex != NULL); - return (void *)rdamutex; -} - -int rda_mutex_wait(void *rdamutex, unsigned int millisec) -{ - osMutexId_t mutex = (osMutexId_t)rdamutex; - osStatus res; - res = osMutexWait(mutex, millisec); - if (res == osOK) { - return NO_ERR; - } else { - return ERR; - } -} - -int rda_mutex_realease(void *rdamutex) -{ - osMutexId_t mutex = (osMutexId_t)rdamutex; - osStatus res; - res = osMutexRelease(mutex); - if(res == osOK) { - return NO_ERR; - } else { - return ERR; - } -} - -int rda_mutex_delete(void *rdamutex) -{ - osMutexId_t mutex = (osMutexId_t)rdamutex; - osStatus res; - res = osMutexDelete(mutex); - free(mutex); - if (res == osOK) { - return NO_ERR; - } else { - return ERR; - } -} - -/* Thread */ -void* rda_thread_new(const char *pcName, - void (*thread)(void *arg), - void *arg, int stacksize, int priority) -{ - osThreadId_t id; - osThreadAttr_t _attr = { 0 }; - mbed_rtos_storage_thread_t *_obj_mem = (mbed_rtos_storage_thread_t *)malloc(sizeof(mbed_rtos_storage_thread_t)); - MBED_ASSERT(_obj_mem != NULL); - memset(_obj_mem, 0, sizeof(mbed_rtos_storage_thread_t)); - _attr.priority = priority; - _attr.stack_size = stacksize; - _attr.name = pcName ? pcName : "rda_unnamed_thread"; - _attr.stack_mem = malloc(stacksize); - MBED_ASSERT(_attr.stack_mem != NULL); - _attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - _attr.cb_mem = _obj_mem; - _attr.tz_module = 0; - - //Fill the stack with a magic word for maximum usage checking - for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) { - ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5; - } - id = osThreadNew(thread, arg, &_attr); - if (id == NULL){ - free(_attr.stack_mem); - free(_attr.cb_mem); - RDA_SYS_PRINT("sys_thread_new create error\n"); - return NULL; - } - return (void *)id; -} - -int rda_thread_delete(void* id) -{ - osStatus ret; - unsigned int *stk = ((osRtxThread_t *)id)->stack_mem; - ret = osThreadTerminate(id); - free(id); - free(stk); - if (ret != osOK) { - return ERR; - } - return NO_ERR; -} - -void* rda_thread_get_id(void) -{ - osThreadId id = osThreadGetId(); - return (void*)id; -} -#endif diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c deleted file mode 100644 index a2c0cd8..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash.c +++ /dev/null @@ -1,1481 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include "critical.h" -#include "wland_flash.h" -#include "wland_dbg.h" -#include "rda5981_flash.h" -#include "wland_flash_wp.h" - -#define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] - -u32 flash_size = FLASH_SIZE; -static u32 user_data_location = RDA5991H_USER_DATA_ADDR; -static u32 third_parter_data_location = RDA5991H_3RDPARTER_DATA_ADDR; -static u32 third_parter_data_len = RDA5991H_3RDPARTER_DATA_LEN; -int rda5981_read_flash(u32 addr, char *buf, u32 len) -{ - int ret = 0; - char *temp_buf = NULL, *temp_buf_aligned; - - addr &= (flash_size -1); - if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { - WLAND_DBG(ERROR, "couldn't read system data\n"); - return -1; - } - - if ((u32)buf % 4) { - temp_buf = malloc(len + 3); - if (temp_buf == NULL) { - ret = -1; - goto out; - } - if ((u32)temp_buf % 4) { - temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); - } else { - temp_buf_aligned = temp_buf; - } - } else { - temp_buf_aligned = buf; - } - - core_util_critical_section_enter(); - spi_flash_flush_cache(); - SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, len); - core_util_critical_section_exit(); - - if (temp_buf_aligned != buf) { - memcpy(buf, temp_buf_aligned, len); - } - -out: - if (temp_buf) { - free(temp_buf); - } - - return ret; -} - -void rda5981_spi_flash_erase_64KB_block(u32 addr) -{ - if (rda_ccfg_hwver() < 4) { - spi_wip_reset_2(); - spi_write_reset_2(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); - wait_busy_down_2(); - spi_wip_reset_2(); - } else { - spi_wip_reset_4(); - spi_write_reset_4(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, CMD_64KB_BLOCK_ERASE | (addr<<8)); - wait_busy_down_4(); - spi_wip_reset_4(); - } -} -void rda5981_spi_erase_partition(void *src, u32 counts) -{ - u32 a4k, a64k, a64kend, a4kend, atmp; - - if (counts > 0x00) { - a4k = ((u32)src ) & (~((0x01UL << 12) - 0x01UL)); - a64k = ((u32)src + (0x01UL << 16) - 0x01UL) & (~((0x01UL << 16) - 0x01UL)); - a64kend = ((u32)src + counts ) & (~((0x01UL << 16) - 0x01UL)); - a4kend = ((u32)src + counts + (0x01UL << 12) - 0x01UL) & (~((0x01UL << 12) - 0x01UL)); - - for (atmp = a4k; atmp < a4kend; atmp += (0x01UL << 12)) { - if (a64kend > a64k) { - if (atmp == a64k) { - for (; atmp < a64kend; atmp += (0x01UL << 16)) { - core_util_critical_section_enter(); - rda5981_spi_flash_erase_64KB_block(atmp); - core_util_critical_section_exit(); - } - if (atmp == a4kend) { - break; - } - } - } - core_util_critical_section_enter(); - rda5981_spi_flash_erase_4KB_sector(atmp); - core_util_critical_section_exit(); - } - } -} -//@len must be 4k aligment -int rda5981_erase_flash(u32 addr, u32 len) -{ - WLAND_DBG(INFO, "erase flash :%x:%x\n", addr, len); - - addr &= (flash_size - 1); - if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { - WLAND_DBG(ERROR, "couldn't erase system data\n"); - return -1; - } - - if (len & (SECTOR_SIZE-1)) { - len = ((len+SECTOR_SIZE) & (~(SECTOR_SIZE-1))); - } - flash_wrtie_protect(addr); - rda5981_spi_erase_partition((void*)addr, len); - flash_wrtie_protect_all(); - return 0; -} - -//@len must be 256 aligment -int rda5981_write_flash(u32 addr, char *buf, u32 len) -{ - int ret = 0; - u8 *temp_buf = NULL, *temp_buf_aligned; - u8 *check_buf = NULL; - - addr &= (flash_size -1); - if (addr < RDA5991H_PARTITION_TABLE_END_ADDR-0x18000000) { - WLAND_DBG(ERROR, "couldn't write system data\n"); - return -1; - } - - if ((u32)buf % 4) { - temp_buf = malloc(len + 3); - if (temp_buf == NULL) { - goto out; - } - if ((u32)temp_buf % 4) { - temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); - } else { - temp_buf_aligned = temp_buf; - } - memcpy(temp_buf_aligned, buf, len); - } else { - temp_buf_aligned = (u8*)buf; - } - flash_wrtie_protect(addr); - core_util_critical_section_enter(); - //RDA5991H_ERASE_FLASH(addr, len); - RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); - core_util_critical_section_exit(); - flash_wrtie_protect_all(); - -#ifdef FLASH_READ_CHECK - if (ret == 0) { - check_buf = malloc(len); - rda5981_read_flash(addr, check_buf, len); - if (memcmp(buf, check_buf, len) == 0) { - ret = 0; - } else { - ret = -1; - } - } -#endif /*FLASH_READ_CHECK*/ - -out: - if (temp_buf) { - free(temp_buf); - } - if (check_buf) { - free(check_buf); - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -rda5991h_user_data wland_user_data; -u8 read_flag = 0; -int rda5981_write_user_data(u8 *data, u16 len, u32 flag) -{ - WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); - - if (!read_flag) { - if (0 == rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data))) { - read_flag = 1; - } else { - return -1; - } - } - - if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || - strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { - memset(&wland_user_data, 0xff, sizeof(wland_user_data)); - wland_user_data.flag = flag; - strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); - } - - wland_user_data.flag |= flag; - - switch (flag) { - case RDA5991H_USER_DATA_FLAG_STA: - memcpy(&wland_user_data.sta_data, data, - min(sizeof(wland_user_data.sta_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_MAC: - memcpy(wland_user_data.mac_addr, data, - min(sizeof(wland_user_data.mac_addr), len)); - break; - case RDA5991H_USER_DATA_FLAG_PMK: - memcpy(wland_user_data.pmk, data, - min(sizeof(wland_user_data.pmk), len)); - break; - case RDA5991H_USER_DATA_FLAG_IP: - memcpy(wland_user_data.ip, data, - min(RDA5991H_USER_DATA_IP_LENGTH, len)); - break; - case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: - memcpy(&wland_user_data.parter_data_len, data, - min(sizeof(wland_user_data.parter_data_len), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER: - memcpy(&wland_user_data.tx_power, data, - min(sizeof(wland_user_data.tx_power), len)); - break; - case RDA5991H_USER_DATA_FLAG_XTAL_CAL: - memcpy(&wland_user_data.xtal_cal, data, - min(sizeof(wland_user_data.xtal_cal), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: - memcpy(&wland_user_data.tx_power_rf, data, - min(sizeof(wland_user_data.tx_power_rf), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: - memcpy(&wland_user_data.tx_power_phy_gn, data, - min(sizeof(wland_user_data.tx_power_phy_gn), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: - memcpy(&wland_user_data.tx_power_phy_b, data, - min(sizeof(wland_user_data.tx_power_phy_b), len)); - break; - case RDA5991H_USER_DATA_FLAG_AP: - memcpy(&wland_user_data.ap_data, data, - min(sizeof(wland_user_data.ap_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_APNET: - memcpy(&wland_user_data.ap_net_data, data, - min(sizeof(wland_user_data.ap_net_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_DHCP: - memcpy(&wland_user_data.dhcp, data, - min(sizeof(wland_user_data.dhcp), len)); - break; - case RDA5991H_USER_DATA_FLAG_UART: - memcpy(&wland_user_data.uart, data, - min(sizeof(wland_user_data.uart), len)); - break; - case RDA5991H_USER_DATA_FLAG_RF: - memcpy(&wland_user_data.rf, data, - min(sizeof(wland_user_data.rf), len)); - break; - case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: - memcpy(&wland_user_data.rf_channels, data, - min(sizeof(wland_user_data.rf_channels), len)); - break; - case RDA5991H_USER_DATA_FLAG_PHY: - memcpy(&wland_user_data.phy, data, - min(sizeof(wland_user_data.phy), len)); - break; - case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: - memcpy(&wland_user_data.phy_channels, data, - min(sizeof(wland_user_data.phy_channels), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: - memcpy(&wland_user_data.tp_offset, data, - min(sizeof(wland_user_data.tp_offset), len)); - break; - default: - return -1; - } - rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); - return rda5981_write_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); -} - -/* - * return 0:ok, else:error. - */ -int rda5981_erase_user_data(u32 flag) -{ - if (!read_flag) { - read_flag = 1; - rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); - } - - if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff - return -1; - } - - if ((wland_user_data.flag & flag) == 0) { - return 0; - } - - wland_user_data.flag &= (~flag); - - if (wland_user_data.flag == 0) { - wland_user_data.flag = RDA5991H_USER_DATA_FLAG_UNINITIALIZED; - } - if (flag & RDA5991H_USER_DATA_FLAG_STA) { - memset(&wland_user_data.sta_data, 0xff, - sizeof(wland_user_data.sta_data)); - } - if (flag & RDA5991H_USER_DATA_FLAG_MAC) { - memset(wland_user_data.mac_addr, 0xff, - sizeof(wland_user_data.mac_addr)); - } - if (flag & RDA5991H_USER_DATA_FLAG_PMK) { - memset(wland_user_data.pmk, 0xff, - sizeof(wland_user_data.pmk)); - } - if (flag & RDA5991H_USER_DATA_FLAG_IP) { - memset(wland_user_data.ip, 0xff, - RDA5991H_USER_DATA_IP_LENGTH); - } - if (flag & RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN) { - memset(&wland_user_data.parter_data_len, 0xff, - sizeof(wland_user_data.parter_data_len)); - } - if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER) { - memset(&wland_user_data.tx_power, 0xff, - sizeof(wland_user_data.tx_power)); - } - if (flag & RDA5991H_USER_DATA_FLAG_XTAL_CAL) { - memset(&wland_user_data.xtal_cal, 0xff, - sizeof(wland_user_data.xtal_cal)); - } - if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_RF) { - memset(&wland_user_data.tx_power_rf, 0xff, - sizeof(wland_user_data.tx_power_rf)); - } - if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN) { - memset(&wland_user_data.tx_power_phy_gn, 0xff, - sizeof(wland_user_data.tx_power_phy_gn)); - } - if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B) { - memset(&wland_user_data.tx_power_phy_b, 0xff, - sizeof(wland_user_data.tx_power_phy_b)); - } - if (flag & RDA5991H_USER_DATA_FLAG_AP) { - memset(&wland_user_data.ap_data, 0xff, - sizeof(wland_user_data.ap_data)); - } - if (flag & RDA5991H_USER_DATA_FLAG_APNET) { - memset(&wland_user_data.ap_net_data, 0xff, - sizeof(wland_user_data.ap_net_data)); - } - if (flag & RDA5991H_USER_DATA_FLAG_DHCP) { - memset(&wland_user_data.dhcp, 0xff, - sizeof(wland_user_data.dhcp)); - } - if (flag & RDA5991H_USER_DATA_FLAG_UART) { - memset(&wland_user_data.uart, 0xff, - sizeof(wland_user_data.uart)); - } - if (flag & RDA5991H_USER_DATA_FLAG_RF) { - memset(&wland_user_data.rf, 0xff, - sizeof(wland_user_data.rf)); - } - if (flag & RDA5991H_USER_DATA_FLAG_RF_CHANNELS) { - memset(&wland_user_data.rf_channels, 0xff, - sizeof(wland_user_data.rf_channels)); - } - if (flag & RDA5991H_USER_DATA_FLAG_PHY) { - memset(&wland_user_data.phy, 0xff, - sizeof(wland_user_data.phy)); - } - if (flag & RDA5991H_USER_DATA_FLAG_PHY_CHANNELS) { - memset(&wland_user_data.phy_channels, 0xff, - sizeof(wland_user_data.phy_channels)); - } - if (flag & RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET) { - memset(&wland_user_data.tp_offset, 0xff, - sizeof(wland_user_data.tp_offset)); - } - rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); - return rda5981_write_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); -} - -/* - * return 0:ok, else:error. - */ -int rda5981_read_user_data(u8 *data, u16 len, u32 flag) -{ - //rda5991h_user_data wland_user_data; - WLAND_DBG(INFO, "Enter, flag:0x%x\r\n", flag); - - if (!read_flag) { - read_flag = 1; - rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); - } - - if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff - return -1; - } - if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { - return -2; - } - if ((wland_user_data.flag & flag) == 0) { - return -3; - } - switch (flag) { - case RDA5991H_USER_DATA_FLAG_STA: - memcpy(data, &wland_user_data.sta_data, - min(sizeof(wland_user_data.sta_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_MAC: - memcpy(data, wland_user_data.mac_addr, - min(sizeof(wland_user_data.mac_addr), len)); - break; - case RDA5991H_USER_DATA_FLAG_PMK: - memcpy(data, wland_user_data.pmk, - min(sizeof(wland_user_data.pmk), len)); - break; - case RDA5991H_USER_DATA_FLAG_IP: - memcpy(data, wland_user_data.ip, - min(RDA5991H_USER_DATA_IP_LENGTH, len)); - break; - case RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN: - memcpy(data, &wland_user_data.parter_data_len, - min(sizeof(wland_user_data.parter_data_len), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER: - memcpy(data, &wland_user_data.tx_power, - min(sizeof(wland_user_data.tx_power), len)); - break; - case RDA5991H_USER_DATA_FLAG_XTAL_CAL: - memcpy(data, &wland_user_data.xtal_cal, - min(sizeof(wland_user_data.xtal_cal), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_RF: - memcpy(data, &wland_user_data.tx_power_rf, - min(sizeof(wland_user_data.tx_power_rf), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_GN: - memcpy(data, &wland_user_data.tx_power_phy_gn, - min(sizeof(wland_user_data.tx_power_phy_gn), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_PHY_B: - memcpy(data, &wland_user_data.tx_power_phy_b, - min(sizeof(wland_user_data.tx_power_phy_b), len)); - break; - case RDA5991H_USER_DATA_FLAG_AP: - memcpy(data, &wland_user_data.ap_data, - min(sizeof(wland_user_data.ap_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_APNET: - memcpy(data, &wland_user_data.ap_net_data, - min(sizeof(wland_user_data.ap_net_data), len)); - break; - case RDA5991H_USER_DATA_FLAG_DHCP: - memcpy(data, &wland_user_data.dhcp, - min(sizeof(wland_user_data.dhcp), len)); - break; - case RDA5991H_USER_DATA_FLAG_UART: - memcpy(data, &wland_user_data.uart, - min(sizeof(wland_user_data.uart), len)); - break; - case RDA5991H_USER_DATA_FLAG_RF: - memcpy(data, &wland_user_data.rf, - min(sizeof(wland_user_data.rf), len)); - break; - case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: - memcpy(data, &wland_user_data.rf_channels, - min(sizeof(wland_user_data.rf_channels), len)); - break; - case RDA5991H_USER_DATA_FLAG_PHY: - memcpy(data, &wland_user_data.phy, - min(sizeof(wland_user_data.phy), len)); - break; - case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: - memcpy(data, &wland_user_data.phy_channels, - min(sizeof(wland_user_data.phy_channels), len)); - break; - case RDA5991H_USER_DATA_FLAG_TX_POWER_OFFSET: - memcpy(data, &wland_user_data.tp_offset, - min(sizeof(wland_user_data.tp_offset), len)); - break; - default: - return -1; - } - return 0; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_mac_addr(u8 *mac_addr) -{ - int ret; - WLAND_DBG(DEBUG, "Enter\r\n"); - ret = rda5981_read_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); - if (ret) { - WLAND_DBG(ERROR, "read mac addr from flash fail\r\n"); - } else { - WLAND_DBG(INFO, "Done(ret:%d)"MACDBG"\r\n", ret, MAC2STRDBG(mac_addr)); - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_write_mac_addr(u8 *mac_addr) -{ - WLAND_DBG(INFO, "Enter"MACDBG"\r\n", MAC2STRDBG(mac_addr)); - return rda5981_write_user_data(mac_addr, 6, RDA5991H_USER_DATA_FLAG_MAC); -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_uart(void) -{ - return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_UART); -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_uart(u32 *uart) -{ - int ret; - WLAND_DBG(DEBUG, "Enter\r\n"); - ret = rda5981_read_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); - if (ret) { - WLAND_DBG(ERROR, "read uart setting from flash fail\r\n"); - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_write_uart(u32 *uart) -{ - return rda5981_write_user_data((u8 *)uart, 4, RDA5991H_USER_DATA_FLAG_UART); -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_sta_data(void) -{ - int ret; - ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK | - RDA5991H_USER_DATA_FLAG_STA); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_sta_data(char *ssid, char *passwd) -{ - int ret; - wland_sta_data_t sta_data; - - WLAND_DBG(INFO, "Enter\r\n"); - - ret = rda5981_read_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); - if (ret == 0) { - strcpy(ssid, sta_data.ssid); - strcpy(passwd, sta_data.key); - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -extern u8 *rda_get_bssinfo_pmk(void); -extern u8 *rda_get_bssinfo_SSID(void); -int rda5981_flash_write_sta_data(const char *ssid, const char *passwd) -{ - int ret = 0, ret1; - wland_sta_data_t sta_data; - u8 *pbss_info_pmk = NULL, *pbss_info_SSID = NULL; - pbss_info_pmk = rda_get_bssinfo_pmk(); - pbss_info_SSID = rda_get_bssinfo_SSID(); - - WLAND_DBG(INFO, "Enter:ssid:%s,pw:%s, pmk:%02x %02x***\r\n", - ssid, passwd, pbss_info_pmk[0], pbss_info_SSID[1]); - if (strlen(ssid) == 0) { - WLAND_DBG(ERROR, "ssid is NULL\n"); - return -1; - } - - memset(&sta_data, 0xff, sizeof(sta_data)); - strcpy(sta_data.ssid, ssid); - strcpy(sta_data.key, passwd); - if (pbss_info_pmk[0] && memcmp(pbss_info_SSID, ssid, 6)==0) { - ret = rda5981_write_user_data(pbss_info_pmk, sizeof(pbss_info_pmk), RDA5991H_USER_DATA_FLAG_PMK); - } - ret1 = rda5981_write_user_data((u8 *)&sta_data, sizeof(sta_data), RDA5991H_USER_DATA_FLAG_STA); - return ret || ret1;; -} - - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_dhcp_data(void) -{ - int ret;//, ret1; - //WLAND_DBG(INFO, "Enter\r\n"); - ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_DHCP); - //ret1 = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PMK); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_dhcp_data(unsigned int *fixip, unsigned int *ip, unsigned int *msk, unsigned int *gw) -{ - int ret; - wland_dhcp_t dhcp; - - WLAND_DBG(INFO, "Enter\r\n"); - - ret = rda5981_read_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); - if (ret == 0) { - *fixip = dhcp.fixip; - *ip = dhcp.ip; - *msk = dhcp.msk; - *gw = dhcp.gw; - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_write_dhcp_data(unsigned int fixip, unsigned int ip, unsigned int msk, unsigned int gw) -{ - int ret = 0; - wland_dhcp_t dhcp; - - memset(&dhcp, 0xff, sizeof(dhcp)); - dhcp.fixip = fixip; - dhcp.ip = ip; - dhcp.msk = msk; - dhcp.gw = gw; - ret = rda5981_write_user_data((u8 *)&dhcp, sizeof(dhcp), RDA5991H_USER_DATA_FLAG_DHCP); - return ret; -} - - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_ap_data(void) -{ - int ret; - ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_AP); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_write_ap_data(const char *ssid, const char *passwd, unsigned char channel) -{ - int ret = 0; - wland_ap_data_t ap_data; - - if (strlen(ssid) == 0) { - WLAND_DBG(ERROR, "ssid is NULL\n"); - return -1; - } - - memset(&ap_data, 0xff, sizeof(ap_data)); - strcpy(ap_data.ssid, ssid); - strcpy(ap_data.key, passwd); - ap_data.channel = channel; - ret = rda5981_write_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_ap_data(char *ssid, char *passwd, unsigned char *channel) -{ - int ret; - wland_ap_data_t ap_data; - - WLAND_DBG(INFO, "Enter\r\n"); - - ret = rda5981_read_user_data((u8 *)&ap_data, sizeof(ap_data), RDA5991H_USER_DATA_FLAG_AP); - if (ret == 0) { - strcpy(ssid, ap_data.ssid); - strcpy(passwd, ap_data.key); - *channel = ap_data.channel; - } - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_erase_ap_net_data(void) -{ - int ret; - ret = rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_APNET); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_write_ap_net_data(unsigned int ip, unsigned int msk, unsigned int gw, - unsigned int dhcps, unsigned int dhcpe) -{ - int ret = 0; - wland_ap_net_data_t ap_net_data; - - WLAND_DBG(INFO, "Enter\r\n"); - - memset(&ap_net_data, 0xff, sizeof(ap_net_data)); - ap_net_data.ip = ip; - ap_net_data.msk = msk; - ap_net_data.gw = gw; - ap_net_data.dhcps = dhcps; - ap_net_data.dhcpe = dhcpe; - - ret = rda5981_write_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); - return ret; -} - -/* - * return 0:ok, else:error. - */ -int rda5981_flash_read_ap_net_data(unsigned int *ip, unsigned int *msk, unsigned int *gw, - unsigned int *dhcps, unsigned int *dhcpe) -{ - int ret = 0; - wland_ap_net_data_t ap_net_data; - - WLAND_DBG(INFO, "Enter\r\n"); - - ret = rda5981_read_user_data((u8 *)&ap_net_data, sizeof(ap_net_data), RDA5991H_USER_DATA_FLAG_APNET); - if (ret == 0) { - *ip = ap_net_data.ip; - *msk = ap_net_data.msk; - *gw = ap_net_data.gw; - *dhcps = ap_net_data.dhcps; - *dhcpe = ap_net_data.dhcpe; - } - return ret; -} - - -int rda5981_flash_read_pmk(u8 *pmk) -{ - WLAND_DBG(INFO, "Enter\r\n"); - return rda5981_read_user_data(pmk, 32, RDA5991H_USER_DATA_FLAG_PMK); -} - -int rda5981_flash_read_ip_addr(u8 *ip_addr, u8 *server_addr) -{ - int ret; - u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; - WLAND_DBG(DEBUG, "Enter\r\n"); - ret = rda5981_read_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); - if (ret) { - WLAND_DBG(ERROR, "read ip addr from flash fail\r\n"); - } else { - memcpy(ip_addr, buf, 4); - memcpy(server_addr, buf+4, 4); - WLAND_DBG(INFO, "read ip:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); - } - return ret; -} - -int rda5981_flash_write_ip_addr(u8 *ip_addr, u8 *server_addr) -{ - u8 buf[RDA5991H_USER_DATA_IP_LENGTH]; - WLAND_DBG(INFO, "write:%u.%u.%u.%u\r\n", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); - memcpy(buf, ip_addr, 4); - memcpy(buf+4, server_addr, 4); - return rda5981_write_user_data(buf, RDA5991H_USER_DATA_IP_LENGTH, RDA5991H_USER_DATA_FLAG_IP); -} - -int rda5981_flash_read_3rdparter_data_length() -{ - int ret; - u32 data_len = 0; - - WLAND_DBG(INFO, "Enter\r\n"); - ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); - if (ret) { - WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); - return -1; - } - return data_len; -} - -int rda5981_flash_read_3rdparter_data(u8 *buf, u32 buf_len) -{ - int ret; - u32 data_len = 0; - - WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); - ret = rda5981_read_user_data((u8 *)(&data_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); - if (ret) { - WLAND_DBG(ERROR, "read parter data length from flash fail(%d)\r\n", ret); - return -1; - } - - if (buf_len < data_len) - WLAND_DBG(ERROR, "The buf you prepared is to small(%u:%u)\r\n", buf_len, data_len); - - data_len = min(buf_len, data_len); - - ret = rda5981_read_flash(third_parter_data_location, - (char *)(buf), data_len); - if (ret) { - WLAND_DBG(ERROR, "read parter data from flash fail(%d)\r\n", ret); - return -2; - } - - return data_len; -} - -int rda5981_flash_erase_3rdparter_data() -{ - return rda5981_erase_user_data(RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); -} - -int rda5981_flash_write_3rdparter_data(const u8 *buf, u32 buf_len) -{ - int ret; - - WLAND_DBG(INFO, "Enter: %u\r\n", buf_len); - if (buf_len > third_parter_data_len) { - WLAND_DBG(ERROR, "buf too long(%u), we have only %x flash space\r\n", - buf_len, third_parter_data_len); - return -1; - } - - rda5981_erase_flash(third_parter_data_location, buf_len); - ret = rda5981_write_flash(third_parter_data_location, - (char *)(buf), buf_len); - if (ret) { - WLAND_DBG(ERROR, "write parter data to flash fail\r\n"); - return -2; - } - - ret = rda5981_write_user_data((u8 *)(&buf_len), 4, RDA5991H_USER_DATA_FLAG_PARTER_DATA_LEN); - if (ret) { - WLAND_DBG(ERROR, "write parter data length to flash fail\r\n"); - return -3; - } - return 0; -} - -int rda5981_set_flash_size(const u32 size) -{ - - WLAND_DBG(INFO, "Enter set flash size: %x\r\n", size); - if (size == 0x100000 || - size == 0x200000 || - size == 0x400000) { - flash_size = size; - return 0; - } - - return -1; -} - -int rda5981_set_user_data_addr(const u32 sys_data_addr, - const u32 user_data_addr, const u32 user_data_len) -{ - WLAND_DBG(INFO, "Enter set userdata addr: %x:%x:%x\r\n", - sys_data_addr, user_data_addr, user_data_len); - if ((sys_data_addr&(SECTOR_SIZE-1)) || (user_data_addr&(SECTOR_SIZE-1))) { - return -1; - } - if (sys_data_addr == user_data_addr) { - return -2; - } - - if (sys_data_addr<=0x18001000 || user_data_addr<=0x18001000) { - return -3; - } - if (sys_data_addr+0x1000 > 0x18000000+flash_size) { - return -4; - } - if (user_data_addr+user_data_len > 0x18000000+flash_size) { - return -5; - } - - user_data_location = sys_data_addr; - third_parter_data_location = user_data_addr; - third_parter_data_len= user_data_len; - return 0; -} - -int rda5981_write_user_data_regs(u8 *reg, u8 *value, u32 flag) -{ - u16 reg16 = 0; - u32 reg32 = 0; - u8 idx = 0; - - if (!read_flag) { - if (0 == rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data))) { - read_flag = 1; - } else { - return -1; - } - } - - if ((wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) || - strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { - memset(&wland_user_data, 0xff, sizeof(wland_user_data)); - wland_user_data.flag = flag; - strcpy((char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG); - } - - wland_user_data.flag |= flag; - - switch (flag) { - case RDA5991H_USER_DATA_FLAG_RF: - if (wland_user_data.rf.valid != 1) { - wland_user_data.rf.valid = 1; - wland_user_data.rf.flag = 0; - } - - reg16 = *((u16 *)reg); - if (wland_user_data.rf.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf.flag & BIT(idx)) && - (wland_user_data.rf.reg_val[idx][0] == reg16)) { - wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); - break; - } else { - continue; - } - } - if ((8 == idx) && (0xFF == wland_user_data.rf.flag)) - return -2; - } - - if ((8 == idx) || (0 == wland_user_data.rf.flag)) { - for (idx = 0; idx < 8; idx++) { - if (!(wland_user_data.rf.flag & BIT(idx))) { - wland_user_data.rf.reg_val[idx][0] = reg16; - wland_user_data.rf.reg_val[idx][1] = *((u16 *)value); - wland_user_data.rf.flag |= BIT(idx); - break; - } else { - continue; - } - } - } - - break; - case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: - if (wland_user_data.rf_channels.valid != 1) { - wland_user_data.rf_channels.valid = 1; - wland_user_data.rf_channels.flag = 0; - } - - reg16 = *((u16 *)reg); - if (wland_user_data.rf_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf_channels.flag & BIT(idx)) && - (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { - memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); - break; - } else { - continue; - } - } - if ((8 == idx) && (0xFF == wland_user_data.rf_channels.flag)) { - return -2; - } - } - - if ((8 == idx) || (0 == wland_user_data.rf_channels.flag)) { - for (idx = 0; idx < 8; idx++) { - if (!(wland_user_data.rf_channels.flag & BIT(idx))) { - wland_user_data.rf_channels.reg_val[idx][0] = reg16; - memcpy(&wland_user_data.rf_channels.reg_val[idx][1], value, 14 * sizeof(u16)); - wland_user_data.rf_channels.flag |= BIT(idx); - break; - } else { - continue; - } - } - } - break; - case RDA5991H_USER_DATA_FLAG_PHY: - if (wland_user_data.phy.valid != 1) { - wland_user_data.phy.valid = 1; - wland_user_data.phy.flag = 0; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy.flag & BIT(idx)) && - (wland_user_data.phy.reg_val[idx][0] == reg32)) { - wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); - break; - } else { - continue; - } - } - if ((8 == idx) && (0xFF == wland_user_data.phy.flag)) { - return -2; - } - } - - if ((8 == idx) || (0 == wland_user_data.phy.flag)) { - for (idx = 0; idx < 8; idx++) { - if (!(wland_user_data.phy.flag & BIT(idx))) { - wland_user_data.phy.reg_val[idx][0] = reg32; - wland_user_data.phy.reg_val[idx][1] = *((u32 *)value); - wland_user_data.phy.flag |= BIT(idx); - break; - } else { - continue; - } - } - } - break; - case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: - if (wland_user_data.phy_channels.valid != 1) { - wland_user_data.phy_channels.valid = 1; - wland_user_data.phy_channels.flag = 0; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy_channels.flag & BIT(idx)) && - (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { - memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); - break; - } else { - continue; - } - } - if ((8 == idx) && (0xFF == wland_user_data.phy_channels.flag)) { - return -2; - } - } - - if ((8 == idx) || (0 == wland_user_data.phy_channels.flag)) { - for (idx = 0; idx < 8; idx++) { - if (!(wland_user_data.phy_channels.flag & BIT(idx))) { - wland_user_data.phy_channels.reg_val[idx][0] = reg32; - memcpy(&wland_user_data.phy_channels.reg_val[idx][1], value, 14 * sizeof(u32)); - wland_user_data.phy_channels.flag |= BIT(idx); - break; - } else { - continue; - } - } - } - break; - default: - WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); - return -3; - } - - rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); - return rda5981_write_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); -} - -int rda5981_erase_user_data_regs(u8 *reg, u32 flag) -{ - u16 reg16 = 0; - u32 reg32 = 0; - u8 idx = 0; - - if (!read_flag) { - if (0 == rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data))) { - read_flag = 1; - } else { - return -1; - } - } - - if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff - return -1; - } - if ((wland_user_data.flag & flag) == 0) { - return 0; - } - switch (flag) { - case RDA5991H_USER_DATA_FLAG_RF: - if (wland_user_data.rf.valid != 1) { - return 0; - } - - reg16 = *((u16 *)reg); - if (wland_user_data.rf.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf.flag & BIT(idx)) && - (wland_user_data.rf.reg_val[idx][0] == reg16)) { - memset(&wland_user_data.rf.reg_val[idx][0], 0xFF, 2 * sizeof(u16)); - wland_user_data.rf.flag &= ~BIT(idx); - break; - } else { - continue; - } - } - } - - if (0 == wland_user_data.rf.flag) { - wland_user_data.rf.valid = 0xFFFFFFFF; - wland_user_data.rf.flag = 0xFFFFFFFF; - wland_user_data.flag &= (~flag); - } - - break; - case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: - if (wland_user_data.rf_channels.valid != 1) { - return 0; - } - - reg16 = *((u16 *)reg); - if (wland_user_data.rf_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf_channels.flag & BIT(idx)) && - (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { - memset(&wland_user_data.rf_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u16)); - wland_user_data.rf_channels.flag &= ~BIT(idx); - break; - } else { - continue; - } - } - } - - if (0 == wland_user_data.rf_channels.flag) { - wland_user_data.rf_channels.valid = 0xFFFFFFFF; - wland_user_data.rf_channels.flag = 0xFFFFFFFF; - wland_user_data.flag &= (~flag); - } - - break; - case RDA5991H_USER_DATA_FLAG_PHY: - if (wland_user_data.phy.valid != 1) { - return 0; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy.flag & BIT(idx)) && - (wland_user_data.phy.reg_val[idx][0] == reg32)) { - memset(&wland_user_data.phy.reg_val[idx][0], 0xFF, 2 * sizeof(u32)); - wland_user_data.phy.flag &= ~BIT(idx); - break; - } else { - continue; - } - } - } - - if (0 == wland_user_data.phy.flag) { - wland_user_data.phy.valid = 0xFFFFFFFF; - wland_user_data.phy.flag = 0xFFFFFFFF; - wland_user_data.flag &= (~flag); - } - - break; - case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: - if (wland_user_data.phy_channels.valid != 1) { - return 0; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy_channels.flag & BIT(idx)) && - (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { - memset(&wland_user_data.phy_channels.reg_val[idx][0], 0xFF, 15 * sizeof(u32)); - wland_user_data.phy_channels.flag &= ~BIT(idx); - break; - } else { - continue; - } - } - } - - if (0 == wland_user_data.phy_channels.flag) { - wland_user_data.phy_channels.valid = 0xFFFFFFFF; - wland_user_data.phy_channels.flag = 0xFFFFFFFF; - wland_user_data.flag &= (~flag); - } - - break; - default: - WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); - return -3; - } - - rda5981_erase_flash(user_data_location, sizeof(wland_user_data)); - return rda5981_write_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data)); -} - - -int rda5981_read_user_data_regs(u8 *reg, u8 *value, u32 flag) -{ - u16 reg16 = 0; - u32 reg32 = 0; - u8 idx = 0; - - if (!read_flag) { - if(0 == rda5981_read_flash(user_data_location, - (char *)(&wland_user_data), sizeof(wland_user_data))) { - read_flag = 1; - } else { - return -1; - } - } - - if (wland_user_data.flag & RDA5991H_USER_DATA_FLAG_UNINITIALIZED) {//flash init is 0xffffffff - return -1; - } - if (strcmp((const char *)(wland_user_data.rda5981_flag), RDA5981_FLAG_FLAG)) { - return -2; - } - if ((wland_user_data.flag & flag) == 0) { - return -3; - } - switch (flag) { - case RDA5991H_USER_DATA_FLAG_RF: - if (wland_user_data.rf.valid != 1) { - return -4; - } - - reg16 = *((u16 *)reg); - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf.flag & BIT(idx)) && - (wland_user_data.rf.reg_val[idx][0] == reg16)) { - memcpy(value, &wland_user_data.rf.reg_val[idx][1], sizeof(u16)); - break; - } else { - continue; - } - } - - if (8 == idx) { - return -4; - } - break; - case RDA5991H_USER_DATA_FLAG_RF_CHANNELS: - if (wland_user_data.rf_channels.valid != 1) { - return -4; - } - - reg16 = *((u16 *)reg); - if (wland_user_data.rf_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.rf_channels.flag & BIT(idx)) && - (wland_user_data.rf_channels.reg_val[idx][0] == reg16)) { - memcpy(value, &wland_user_data.rf_channels.reg_val[idx][1], 14 * sizeof(u16)); - break; - } else { - continue; - } - } - } - - if (8 == idx) { - return -4; - } - break; - case RDA5991H_USER_DATA_FLAG_PHY: - if (wland_user_data.phy.valid != 1) { - return -4; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy.flag & BIT(idx)) && - (wland_user_data.phy.reg_val[idx][0] == reg32)) { - memcpy(value, &wland_user_data.phy.reg_val[idx][1], sizeof(u32)); - break; - } else { - continue; - } - } - } - - if (8 == idx) { - return -4; - } - break; - case RDA5991H_USER_DATA_FLAG_PHY_CHANNELS: - if (wland_user_data.phy_channels.valid != 1) { - return -4; - } - - reg32 = *((u32 *)reg); - if (wland_user_data.phy_channels.flag != 0) { - for (idx = 0; idx < 8; idx++) { - if ((wland_user_data.phy_channels.flag & BIT(idx)) && - (wland_user_data.phy_channels.reg_val[idx][0] == reg32)) { - memcpy(value, &wland_user_data.phy_channels.reg_val[idx][1], 14 * sizeof(u32)); - break; - } else { - continue; - } - } - } - - if (8 == idx) { - return -4; - } - break; - default: - WLAND_DBG(ERROR, "Unknown flag:0x%08x\n", flag); - return -3; - } - - return 0; -} - -int rda5981_flash_get_mid(u8 *mid) -{ - *mid = 0xC8; - - return 0; -} - -int rda5981_flash_get_did(u8 *did) -{ - *did = 0x13; - - return 0; -} - -int rda5981_flash_get_jdid(u16 *jdid) -{ - *jdid = 0x4014; - - return 0; -} - -int rda5981_read_default_config(char *buf, u32 len, u32 flag) -{ - int ret = 0; - u32 addr; - u32 addr_offset = 0; - char *temp_buf = NULL, *temp_buf_aligned; - - switch (flag) { - case RDA5981_VBAT_CAL: - addr = 0x18000088; - break; - case RDA5981_GPADC0_CAL: - case RDA5981_GPADC1_CAL: - addr = 0x1800008C; - break; - case RDA5981_PRODUCT_ID: - addr = 0x18000084; - break; - case RDA5981_POWER_CLASS: - addr = 0x18000085; - break; - default: - WLAND_DBG(ERROR, "Unknown flag\n"); - return -1; - } - - addr_offset = addr % 4; - addr = (addr - addr_offset) & (flash_size -1); - - if (((u32)buf % 4) || (addr_offset != 0)) { - temp_buf = (char *)malloc(addr_offset + len + 4); - if (temp_buf == NULL) { - ret = -1; - goto out; - } - if ((u32)temp_buf % 4) { - temp_buf_aligned = temp_buf + (4 - (u32)temp_buf % 4); - } else { - temp_buf_aligned = temp_buf; - } - } else { - temp_buf_aligned = buf; - } - - core_util_critical_section_enter(); - spi_flash_flush_cache(); - SPI_FLASH_READ_DATA_FOR_MBED((void *)addr, temp_buf_aligned, (len + addr_offset)); - core_util_critical_section_exit(); - - if (temp_buf_aligned != buf) { - memcpy(buf, temp_buf_aligned + addr_offset, len); - } -out: - if (temp_buf) { - free(temp_buf); - } - return ret; -} - -int rda5981_flash_read_vbat_cal(float *k, float *b) -{ - int ret = 0; - u32 value = 0; - u32 x1 = 0;//y1 3.0f - u32 x2 = 0;//y2 4.2f - float k_tmp = 0; - float b_tmp = 0; - - ret = rda5981_read_default_config((char *)&value, 4, RDA5981_VBAT_CAL); - - if (ret < 0) { - WLAND_DBG(ERROR, "read vbat_cal form flash fail\n"); - return -1; - } - if ((0 == (value & 0xFFFFFUL)) || (0xFFFFFUL == (value & 0xFFFFFUL))) { - WLAND_DBG(ERROR, "invalid vbat_cal:0x%08x\n", value); - return -1; - } else { - x1 = value & 0x3FFUL; - x2 = (value >> 10) & 0x3FFUL; - } - - if (x1 == x2) { - return -1; - } - - k_tmp = (4.2f - 3.0f) / (float)(x2 - x1); - b_tmp = 4.2f - k_tmp * x2; - - *k = k_tmp; - *b = b_tmp; - - return ret; -} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c deleted file mode 100644 index 6ff0181..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_flash_wp.c +++ /dev/null @@ -1,366 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed_interface.h" -#include "wland_flash.h" - -//#define FLASH_PROTECT_ENABLE - -#define FLASH_CTL_REG_BASE 0x17fff000 -#define FLASH_CTL_TX_CMD_ADDR_REG (FLASH_CTL_REG_BASE + 0x00) -#define FLASH_CTL_TX_BLOCK_SIZE_REG (FLASH_CTL_REG_BASE + 0x04) -#define FLAHS_CTL_TX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x08) -#define FLASH_CTL_STATUS_REG (FLASH_CTL_REG_BASE + 0x0c) -#define FLAHS_CTL_RX_FIFO_DATA_REG (FLASH_CTL_REG_BASE + 0x10) - -#define WRITE_REG32(REG, VAL) ((*(volatile unsigned int*)(REG)) = (unsigned int)(VAL)) -#define WRITE_REG8(REG, VAL) ((*(volatile unsigned char*)(REG)) = (unsigned char)(VAL)) -#define MREAD_WORD(addr) *((volatile unsigned int *)(addr)) - -#define MID_GD 0xC8 -#define MID_WINBOND 0xEF - -#define FLASH_1M 0x100000 -#define FLASH_2M 0x200000 -#define FLASH_4M 0x400000 -extern unsigned int flash_size; - -#ifdef FLASH_PROTECT_ENABLE - -#define FLASH_WP_MASK 0x407c -#define FLASH_WP_NONE 0x0000 -#define FLASH_WP_ALL 0x1c - -#define FLASH_4M_WP_4K 0x0064 -#define FLASH_4M_WP_8K 0x0068 -#define FLASH_4M_WP_16K 0x006c -#define FLASH_4M_WP_32K 0x0070 -#define FLASH_4M_WP_1_64 0x0024 -#define FLASH_4M_WP_1_32 0x0028 -#define FLASH_4M_WP_1_16 0x002c -#define FLASH_4M_WP_1_8 0x0030 -#define FLASH_4M_WP_1_4 0x0034 -#define FLASH_4M_WP_1_2 0x0038 -#define FLASH_4M_WP_3_4 0x4014 -#define FLASH_4M_WP_7_8 0x4010 -#define FLASH_4M_WP_15_16 0x400c -#define FLASH_4M_WP_31_32 0x4008 -#define FLASH_4M_WP_63_64 0x4004 -#define FLASH_4M_WP_127_128 0x4058 -#define FLASH_4M_WP_255_256 0x404C -#define FLASH_4M_WP_1023_1024 0x4044 - -#define FLASH_2M_WP_4K 0x0064 -#define FLASH_2M_WP_8K 0x0068 -#define FLASH_2M_WP_16K 0x006c -#define FLASH_2M_WP_32K 0x0070 -#define FLASH_2M_WP_1_32 0x0024 -#define FLASH_2M_WP_1_16 0x0028 -#define FLASH_2M_WP_1_8 0x002c -#define FLASH_2M_WP_1_4 0x0050 -#define FLASH_2M_WP_1_2 0x0051 -#define FLASH_2M_WP_3_4 0x4010 -#define FLASH_2M_WP_7_8 0x400c -#define FLASH_2M_WP_15_16 0x4004 -#define FLASH_2M_WP_31_32 0x4000 -#define FLASH_2M_WP_63_64 0x4050 -#define FLASH_2M_WP_127_128 0x404c -#define FLASH_2M_WP_255_256 0x4048 -#define FLASH_2M_WP_511_512 0x4044 - - -#define FLASH_1M_WP_4K 0x0064 -#define FLASH_1M_WP_8K 0x0068 -#define FLASH_1M_WP_16K 0x006c -#define FLASH_1M_WP_32K 0x0070 -#define FLASH_1M_WP_1_16 0x0024 -#define FLASH_1M_WP_1_8 0x0028 -#define FLASH_1M_WP_1_4 0x002c -#define FLASH_1M_WP_1_2 0x0050 -#define FLASH_1M_WP_3_4 0x400C -#define FLASH_1M_WP_7_8 0x4008 -#define FLASH_1M_WP_15_16 0x4004 -#define FLASH_1M_WP_31_32 0x4050 -#define FLASH_1M_WP_63_64 0x404C -#define FLASH_1M_WP_127_128 0x4048 -#define FLASH_1M_WP_255_256 0x4044 - -static unsigned short flash_wrtie_protect_4M(unsigned short status, unsigned int offset) -{ - unsigned int wp = FLASH_WP_NONE; - if (offset >= flash_size - flash_size/1024) { - wp = FLASH_4M_WP_1023_1024; - } else if(offset >= flash_size - flash_size/256) { - wp = FLASH_4M_WP_255_256; - } else if(offset >= flash_size - flash_size/128) { - wp = FLASH_4M_WP_127_128; - } else if(offset >= flash_size - flash_size/64) { - wp = FLASH_4M_WP_63_64; - } else if(offset >= flash_size - flash_size/32) { - wp = FLASH_4M_WP_31_32; - } else if(offset >= flash_size - flash_size/16) { - wp = FLASH_4M_WP_15_16; - } else if(offset >= flash_size - flash_size/8) { - wp = FLASH_4M_WP_7_8; - } else if(offset >= flash_size - flash_size/4) { - wp = FLASH_4M_WP_3_4; - } else if(offset >= flash_size/2) { - wp = FLASH_4M_WP_1_2; - } else if(offset >= flash_size/4) { - wp = FLASH_4M_WP_1_4; - } else if(offset >= flash_size/8) { - wp = FLASH_4M_WP_1_8; - } else if(offset >= flash_size/16) { - wp = FLASH_4M_WP_1_16; - } else if(offset >= flash_size/32) { - wp = FLASH_4M_WP_1_32; - } else if(offset >= flash_size/64) { - wp = FLASH_4M_WP_1_64; - } else if(offset >= 32 * 1024) { - wp = FLASH_4M_WP_32K; - } else if(offset >= 16 * 1024) { - wp = FLASH_4M_WP_16K; - } else if(offset >= 8 * 1024) { - wp = FLASH_4M_WP_8K; - } else if(offset >= 4 * 1024) { - wp = FLASH_4M_WP_4K; - } - - return (status & ~FLASH_WP_MASK) | wp; - -} - -static unsigned short flash_wrtie_protect_2M(unsigned short status, unsigned int offset) -{ - unsigned int wp = FLASH_WP_NONE; - if (offset >= flash_size - flash_size/256) { - wp = FLASH_2M_WP_255_256; - } else if(offset >= flash_size - flash_size/128) { - wp = FLASH_2M_WP_127_128; - } else if(offset >= flash_size - flash_size/64) { - wp = FLASH_2M_WP_63_64; - } else if(offset >= flash_size - flash_size/32) { - wp = FLASH_2M_WP_31_32; - } else if(offset >= flash_size - flash_size/16) { - wp = FLASH_2M_WP_15_16; - } else if(offset >= flash_size - flash_size/8) { - wp = FLASH_2M_WP_7_8; - } else if(offset >= flash_size - flash_size/4) { - wp = FLASH_2M_WP_3_4; - } else if(offset >= flash_size/2) { - wp = FLASH_2M_WP_1_2; - } else if(offset >= flash_size/4) { - wp = FLASH_2M_WP_1_4; - } else if(offset >= flash_size/8) { - wp = FLASH_2M_WP_1_8; - } else if(offset >= flash_size/16) { - wp = FLASH_2M_WP_1_16; - } else if(offset >= flash_size/32) { - wp = FLASH_2M_WP_1_32; - } else if(offset >= 32 * 1024) { - wp = FLASH_2M_WP_32K; - } else if(offset >= 16 * 1024) { - wp = FLASH_2M_WP_16K; - } else if(offset >= 8 * 1024) { - wp = FLASH_2M_WP_8K; - } else if(offset >= 4 * 1024) { - wp = FLASH_2M_WP_4K; - } - - return (status & ~FLASH_WP_MASK) | wp; - -} - -static unsigned short flash_wrtie_protect_1M(unsigned short status, unsigned int offset) -{ - unsigned int wp = FLASH_WP_NONE; - - if (offset >= flash_size - flash_size/256) { - wp = FLASH_1M_WP_255_256; - } else if(offset >= flash_size - flash_size/128) { - wp = FLASH_1M_WP_127_128; - } else if(offset >= flash_size - flash_size/64) { - wp = FLASH_1M_WP_63_64; - } else if(offset >= flash_size - flash_size/32) { - wp = FLASH_1M_WP_31_32; - } else if(offset >= flash_size - flash_size/16) { - wp = FLASH_1M_WP_15_16; - } else if(offset >= flash_size - flash_size/8) { - wp = FLASH_1M_WP_7_8; - } else if(offset >= flash_size - flash_size/4) { - wp = FLASH_1M_WP_3_4; - } else if(offset >= flash_size/2) { - wp = FLASH_1M_WP_1_2; - } else if(offset >= flash_size/4) { - wp = FLASH_1M_WP_1_4; - } else if(offset >= flash_size/8) { - wp = FLASH_1M_WP_1_8; - } else if(offset >= flash_size/16) { - wp = FLASH_1M_WP_1_16; - } else if(offset >= 32 * 1024) { - wp = FLASH_1M_WP_32K; - } else if(offset >= 16 * 1024) { - wp = FLASH_1M_WP_16K; - } else if(offset >= 8 * 1024) { - wp = FLASH_1M_WP_8K; - } else if(offset >= 4 * 1024) { - wp = FLASH_1M_WP_4K; - } - - return (status & ~FLASH_WP_MASK) | wp; - -} - -void flash_wrtie_protect_all() -{ - unsigned short status; - unsigned char r1, r2; - core_util_critical_section_enter(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); - wait_busy_down(); - r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); - wait_busy_down(); - r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - //mbed_error_printf("status %x %x\r\n", r2, r1); - - status = (r2 << 8) | r1; - status = (status & ~FLASH_WP_MASK) | FLASH_WP_ALL; - //mbed_error_printf("status %04x\r\n", status); - - spi_write_reset(); - wait_busy_down(); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); - wait_busy_down(); - spi_wip_reset(); - core_util_critical_section_exit(); - return; -} - -void flash_wrtie_protect_none() -{ - unsigned short status; - unsigned char r1, r2; - core_util_critical_section_enter(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); - wait_busy_down(); - r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); - wait_busy_down(); - r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - //mbed_error_printf("status %x %x\r\n", r2, r1); - - status = (r2 << 8) | r1; - status = status & ~FLASH_WP_MASK; - //mbed_error_printf("status %04x\r\n", status); - - spi_write_reset(); - wait_busy_down(); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); - wait_busy_down(); - spi_wip_reset(); - core_util_critical_section_exit(); - return; -} - -void flash_wrtie_protect(unsigned int offset) -{ - unsigned short status; - unsigned char r1, r2; - core_util_critical_section_enter(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x05); - wait_busy_down(); - r1 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x35); - wait_busy_down(); - r2 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - //mbed_error_printf("status %x %x\r\n", r2, r1); - - status = (r2 << 8) | r1; - if (flash_size == FLASH_4M) { - status = flash_wrtie_protect_4M(status, offset); - } else if(flash_size == FLASH_2M) { - status = flash_wrtie_protect_2M(status, offset); - } else if(flash_size == FLASH_1M) { - status = flash_wrtie_protect_1M(status, offset); - } else [ - LWIP_DEBUGF(NETIF_DEBUG,"flash_size is error\r\n"); - } - //mbed_error_printf("status %04x\r\n", status); - - spi_write_reset(); - wait_busy_down(); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, (status&0xff)); - WRITE_REG8(FLAHS_CTL_TX_FIFO_DATA_REG, ((status>>8)&0xff)); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x01); - wait_busy_down(); - spi_wip_reset(); - core_util_critical_section_exit(); - return; -} -#else -void flash_wrtie_protect_all() -{ - return; -} - -void flash_wrtie_protect_none() -{ - return; -} - -void flash_wrtie_protect(unsigned int offset) -{ - return; -} - -#endif -void rda5981_flash_init() -{ - unsigned int status3, status4, status5; - core_util_critical_section_enter(); - WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); - status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - - wait_busy_down(); - spi_wip_reset(); - WRITE_REG32(FLASH_CTL_TX_CMD_ADDR_REG, 0x9F); - wait_busy_down(); - //WRITE_REG32(FLASH_CTL_TX_BLOCK_SIZE_REG, 3<<8); - //wait_busy_down(); - status3 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - status4 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - status5 = MREAD_WORD(FLAHS_CTL_RX_FIFO_DATA_REG); - core_util_critical_section_exit(); - - if ((status5&0xff != 0x14) && (status5&0xff != 0x15) && (status5&0xff != 0x16)) { - mbed_error_printf("flash size error\r\n"); - return; - } - flash_size = (1 << (status5&0xff)); - flash_wrtie_protect_all(); - - return; -} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c deleted file mode 100644 index 05a85ab..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/lwip-wifi/arch/TARGET_RDA/TARGET_UNO_91H/src/wland_ota.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "wland_ota.h" -#include "wland_flash.h" -#include "rda5981_ota.h" -#include "wland_dbg.h" -#include "wland_types.h" -#include "critical.h" -#include -#include - -#define IMAGE_MAGIC 0xAEAE - -u32 wland_ota_partition_addr = 0; -u32 wland_ota_partition_len = 0; -u32 wland_crc_result = ~0UL; - -static u32 crc32(const u8 *p, u32 len, u32 crc) -{ - const u32 *crc32_tab = (const u32 *)CRC32_TABLE_ADDR; - - if (rda_ccfg_hwver() >= 4) { - crc32_tab = (const u32 *)CRC32_TABLE_ADDR_4; - } - /* Calculate CRC */ - while(len--) { - crc = crc32_tab[((crc & 0xFF) ^ *p++)] ^ (crc >> 8); - } - - return crc; -} - -static int rda5981_ota_erase_flash(u32 addr, u32 len) -{ - addr &= (flash_size -1); - rda5981_spi_erase_partition((void *)addr, len); - return 0; -} -//write without erase -static int rda5981_ota_write_flash(u32 addr, char *buf, u32 len) -{ - int ret = 0; - u8 *temp_buf = NULL, *temp_buf_aligned; - - addr &= (flash_size -1); - if ((u32)buf % 4) { - temp_buf = malloc(len + 3); - if (temp_buf == NULL) { - goto out; - } - if ((u32)temp_buf % 4) { - temp_buf_aligned = temp_buf + (4-(u32)temp_buf%4); - } else { - temp_buf_aligned = temp_buf; - } - memcpy(temp_buf_aligned, (unsigned char *)buf, len); - } else { - temp_buf_aligned = (u8 *)buf; - } - core_util_critical_section_enter(); - RDA5991H_WRITE_FLASH(addr, temp_buf_aligned, len); - core_util_critical_section_exit(); - -out: - if (temp_buf) { - free(temp_buf); - } - return ret; -} - -int rda5981_write_partition_start(u32 addr, u32 img_len) -{ - if (addr < 0x18001000 || addr+img_len>0x18000000+flash_size) { - WLAND_DBG(ERROR,"write partition start addr error. (0x%08x, %u)\r\n", addr, img_len); - return -1; - } - if (addr%0x1000 || img_len%0x1000) { - WLAND_DBG(ERROR,"write partition start length error.(mast be 4k alignment) (0x%08x, %u)\r\n", addr, img_len); - return -1; - } - - WLAND_DBG(INFO, "rda5981_write_partition_start:0x%08x, %u\r\n", addr, img_len); - wland_ota_partition_addr = addr; - wland_ota_partition_len = img_len; - wland_crc_result = ~0U; - - rda5981_ota_erase_flash(addr, img_len); - return 0; -} -int rda5981_write_partition(u32 offset, const u8 *buf, u32 len) -{ - if (wland_ota_partition_addr==0 || offset+len>wland_ota_partition_len) { - WLAND_DBG(ERROR,"write partition error. out of start addr(0x%08x, %u). (0x%08x, %u)\r\n", - wland_ota_partition_addr, wland_ota_partition_len, offset, len); - return -1; - } - if (len%0x400) { - WLAND_DBG(ERROR,"write partition length error.(mast be 1k alignment) (0x%08x, %u)\r\n", offset, len); - return -1; - } - WLAND_DBG(DEBUG, "rda5981_write_partition:0x%08x, %u.(%02x)\r\n", - wland_ota_partition_addr + offset, len, buf[0]); - wland_crc_result = crc32(buf, len, wland_crc_result); - - WLAND_DBG(DEBUG, "rda5981_write_partition: wland_crc_result 0x%08x\r\n", - wland_crc_result); - return rda5981_ota_write_flash(wland_ota_partition_addr + offset, (char *)buf, len); - //return rda5981_write_flash(wland_ota_partition_addr + offset, buf, len); -} -int rda5981_write_partition_end(void) -{ - WLAND_DBG(INFO, "check crc32:0x%08x, %u\r\n", wland_ota_partition_addr, wland_ota_partition_len); - if (wland_ota_partition_addr == 0) { - WLAND_DBG(ERROR,"OTA is not started\r\n"); - return -1; - } - core_util_critical_section_enter(); - spi_flash_flush_cache(); - //u32 crc32_check = crc32(wland_ota_partition_addr, wland_ota_partition_len, ~0U); - u32 crc32_check = bootrom_crc32((unsigned char *)wland_ota_partition_addr, wland_ota_partition_len); - core_util_critical_section_exit(); - WLAND_DBG(INFO, "rda5981_write_partition_end:0x%08x:0x%08x\r\n", wland_crc_result, crc32_check); - wland_ota_partition_addr = 0UL; - - if (crc32_check == wland_crc_result) { - return 0; - } else { - WLAND_DBG(ERROR,"check crc32 error\r\n"); - return -1; - } -} diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp deleted file mode 100644 index 9ab3557..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "cmsis_os.h" -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "mbed_shared_queues.h" -#include "netsocket/nsapi_types.h" -#include "lwip/arch.h" -#include "lwip/pbuf.h" -#include "rda5991h_wland.h" -#include "rda5981x_emac_config.h" -#include "rda5981x_emac.h" -#include "rda_sys_wrapper.h" -#include "maclib_task.h" - -#define RDA_HWADDR_SIZE (6) -#define RDA_ETH_MTU_SIZE 1500 -#define RDA_ETH_IF_NAME "st" - -#define RX_PRIORITY (osPriorityNormal) -#define TX_PRIORITY (osPriorityNormal) -#define PHY_PRIORITY (osPriorityNormal) - -extern void *packet_rx_queue; - -RDA5981x_EMAC::RDA5981x_EMAC() -{ -} - -/** - * This function should do the actual transmission of the packet. The packet is - * contained in the memory buffer chain that is passed to the function. - * - * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return true if the packet could be sent - * false value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ -bool RDA5981x_EMAC::link_out(emac_mem_buf_t *buf) -{ - emac_mem_buf_t *q, *p = buf; - - u32_t actual_txlen = 0; - u8_t **data = NULL; - u16_t retry = 400; - - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output enter, p:%08x\n", p)); - - while ((data == NULL) && (retry-- > 0)) { - data = (u8_t**)wland_get_databuf(); - osThreadYield(); - } - if (data == NULL) { - LWIP_DEBUGF(NETIF_DEBUG, ("rda91h_low_level_output, no PKT buf\r\n")); - memory_manager->free(buf); - return false; - } - - for (q = p; q != NULL; q = memory_manager->get_next(q)) { - /* Send the data from the pbuf to the interface, one pbuf at a - time. The size of the data in each pbuf is kept in the ->len - variable. */ - memcpy(&((*data)[actual_txlen+2]), memory_manager->get_ptr(q), memory_manager->get_len(q));//reserve wid header length - actual_txlen += memory_manager->get_len(q); - if (actual_txlen > 1514 || actual_txlen > memory_manager->get_total_len(p)) { - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output err, actual_txlen:%d, tot_len%d\n", actual_txlen, memory_manager->get_total_len(p))); - memory_manager->free(buf); - return false; - } - } - - /* Signal rda5996 that packet should be sent */ - if (actual_txlen == memory_manager->get_total_len(p)) { - wland_txip_data((void*)data, actual_txlen, 0); - memory_manager->free(buf); - return true; - } - - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_output pkt len mismatch, actual_txlen:%d, tot_len%d\n", - actual_txlen, memory_manager->get_total_len(p))); - - memory_manager->free(buf); - return false; -} - -/** - * Should allocate a contiguous memory buffer and transfer the bytes of the incoming - * packet to the buffer. - * - * @param buf If a frame was received and the memory buffer allocation was successful, a memory - * buffer filled with the received packet (including MAC header) - * @return negative value when no more frames, - * zero when frame is received - */ -emac_mem_buf_t * RDA5981x_EMAC::low_level_input(u8_t *data, int len) -{ - emac_mem_buf_t *p, *q; - u16_t index = 0; - - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input enter, rxlen:%d\n", len)); - - /* Obtain the size of the packet and put it into the "len" - variable. */ - if (!len) { - return NULL; - } - - /* We allocate a pbuf chain of pbufs from the pool. */ - p = memory_manager->alloc_pool(len, 0); - if (p != NULL) { - /* We iterate over the pbuf chain until we have read the entire - * packet into the pbuf. */ - for (q = p; q != NULL; q = memory_manager->get_next(q)) { - /* Read enough bytes to fill this pbuf in the chain. The - * available data in the pbuf is given by the q->len - * variable. - * This does not necessarily have to be a memcpy, you can also preallocate - * pbufs for a DMA-enabled MAC and after receiving truncate it to the - * actually received size. In this case, ensure the tot_len member of the - * pbuf is the sum of the chained pbuf len members. - */ - /* load rx data from 96 to local mem_pool */ - memcpy(memory_manager->get_ptr(q), &data[index], memory_manager->get_len(q)); - index += memory_manager->get_len(q); - - if (index >= len) { - break; - } - } - - } else { - /* Drop this packet */ - LWIP_DEBUGF(NETIF_DEBUG, ("low_level_input pbuf_alloc fail, rxlen:%d\n", len)); - - return NULL; - } - return p; -} - - -/** \brief Attempt to read a packet from the EMAC interface. - * - */ -void RDA5981x_EMAC::packet_rx() -{ - rda_msg msg; - packet_rx_queue = rda_mail_create(10, sizeof(unsigned int)*4); - /* move received packet into a new buf */ - while (1) { - emac_mem_buf_t *p = NULL; - rda_mail_get(packet_rx_queue, (void*)&msg, osWaitForever); - switch(msg.type) { - case 0: - p = low_level_input((unsigned char*)msg.arg1, msg.arg2); - if (p == NULL) { - break; - } - if (p) { - emac_link_input_cb(p); - } - break; - case 1: - emac_link_state_cb(msg.arg1); - break; - default: - break; - } - } -} - -void RDA5981x_EMAC::thread_function(void *pvParameters) -{ - static struct RDA5981x_EMAC *rda5981x_enet = static_cast(pvParameters); - rda5981x_enet->packet_rx(); -} - -bool RDA5981x_EMAC::power_up() -{ - /* Initialize the hardware */ - static int init_flag = 0; - if (init_flag == 0) { - wland_reg_func(); - rda_thread_new("maclib_thread", maclib_task, NULL, DEFAULT_THREAD_STACKSIZE*8, PHY_PRIORITY); - rda_thread_new("wland_thread", wland_task, NULL, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); - rda_thread_new("packet_rx", RDA5981x_EMAC::thread_function, this, DEFAULT_THREAD_STACKSIZE*5, PHY_PRIORITY); - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(100); - wland_sta_init(); - init_flag = 1; - } - - return true; -} - -uint32_t RDA5981x_EMAC::get_mtu_size() const -{ - return RDA_ETH_MTU_SIZE; -} - -uint32_t RDA5981x_EMAC::get_align_preference() const -{ - return 0; -} - -void RDA5981x_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, RDA_ETH_IF_NAME, (size < sizeof(RDA_ETH_IF_NAME)) ? size : sizeof(RDA_ETH_IF_NAME)); -} - -uint8_t RDA5981x_EMAC::get_hwaddr_size() const -{ - return RDA_HWADDR_SIZE; -} - -bool RDA5981x_EMAC::get_hwaddr(uint8_t *addr) const -{ - mbed_mac_address((char *)addr); - return true; -} - -void RDA5981x_EMAC::set_hwaddr(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void RDA5981x_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void RDA5981x_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void RDA5981x_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void RDA5981x_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void RDA5981x_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void RDA5981x_EMAC::power_down() -{ - /* No-op at this stage */ -} - -void RDA5981x_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -RDA5981x_EMAC &RDA5981x_EMAC::get_instance() -{ - static RDA5981x_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return RDA5981x_EMAC::get_instance(); -} - diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h deleted file mode 100644 index fa95ba4..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac.h +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32_EMAC_H_ -#define STM32_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Mutex.h" - -class RDA5981x_EMAC : public EMAC { -public: - RDA5981x_EMAC(); - - static RDA5981x_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - void packet_rx(); - emac_mem_buf_t * low_level_input(u8_t *data, int len); - static void thread_function(void *pvParameters); - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - -}; - -#endif /* K64F_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h b/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h deleted file mode 100644 index 717d423..0000000 --- a/features/netsocket/emac-drivers/TARGET_RDA_EMAC/rda5981x_emac_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2019 Unisoc Communications Inc. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32XX_EMAC_CONFIG_H__ -#define STM32XX_EMAC_CONFIG_H__ - -#define THREAD_STACKSIZE 512 - -#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp deleted file mode 100644 index 6484f53..0000000 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* Copyright (c) 2018 Renesas Electronics Corporation. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "cmsis_os.h" -#include "rtos/ThisThread.h" -#include "netsocket/nsapi_types.h" -#include "mbed_shared_queues.h" -#include "rza1_eth.h" -#include "rza1_eth_ext.h" -#include "rza1_emac.h" - -#define RZ_A1_ETH_IF_NAME "en" - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() { - return RZ_A1_EMAC::get_instance(); -} - -RZ_A1_EMAC &RZ_A1_EMAC::get_instance() { - static RZ_A1_EMAC emac; - return emac; -} - -RZ_A1_EMAC::RZ_A1_EMAC() : hwaddr(), hwaddr_set(false), power_on(false), connect_sts(false), - link_mode_last(NEGO_FAIL), recvThread(osPriorityNormal, 896) -{ -} - -uint32_t RZ_A1_EMAC::get_mtu_size() const -{ - return 1500; -} - -uint32_t RZ_A1_EMAC::get_align_preference() const -{ - return 0; -} - -void RZ_A1_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, RZ_A1_ETH_IF_NAME, (size < sizeof(RZ_A1_ETH_IF_NAME)) ? size : sizeof(RZ_A1_ETH_IF_NAME)); -} - -uint8_t RZ_A1_EMAC::get_hwaddr_size() const -{ - return 6; -} - -bool RZ_A1_EMAC::get_hwaddr(uint8_t *addr) const -{ - return false; -} - -void RZ_A1_EMAC::set_hwaddr(const uint8_t *addr) -{ - memcpy(hwaddr, addr, sizeof(hwaddr)); - hwaddr_set = true; - - /* Reconnect */ - if (power_on != false) { - rza1_ethernet_cfg_t ethcfg; - ethcfg.int_priority = 6; - ethcfg.recv_cb = &_recv_callback; - ethcfg.ether_mac = NULL; - ethcfg.ether_mac = (char *)hwaddr; - ethernetext_init(ðcfg); - } -} - -bool RZ_A1_EMAC::link_out(emac_mem_buf_t *buf) -{ - emac_mem_buf_t *copy_buf = buf; - uint32_t retry_cnt; - bool result = false; - int write_size; - int total_write_size = 0; - - while ((copy_buf != NULL) && (memory_manager->get_ptr(copy_buf) != NULL) && (memory_manager->get_len(copy_buf) != 0)) { - for (retry_cnt = 0; retry_cnt < 100; retry_cnt++) { - write_size = rza1_ethernet_write((char *)memory_manager->get_ptr(copy_buf), memory_manager->get_len(copy_buf)); - if (write_size != 0) { - total_write_size += write_size; - break; - } - osDelay(1); - } - copy_buf = memory_manager->get_next(copy_buf); - } - memory_manager->free(buf); - - if (total_write_size > 0) { - if (rza1_ethernet_send() == 1) { - result = true; - } - } - - return result; -} - -bool RZ_A1_EMAC::power_up() -{ - if (power_on != false) { - return true; - } - - rza1_ethernet_cfg_t ethcfg; - ethcfg.int_priority = 6; - ethcfg.recv_cb = &_recv_callback; - ethcfg.ether_mac = NULL; - if (hwaddr_set) { - ethcfg.ether_mac = (char *)hwaddr; - } - ethernetext_init(ðcfg); - - /* task */ - recvThread.start(mbed::callback(this, &RZ_A1_EMAC::recv_task)); - phy_task_handle = mbed::mbed_event_queue()->call_every(200, mbed::callback(this, &RZ_A1_EMAC::phy_task)); - - power_on = true; - return true; -} - -void RZ_A1_EMAC::power_down() -{ - power_on = false; -} - -void RZ_A1_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void RZ_A1_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void RZ_A1_EMAC::add_multicast_group(const uint8_t *addr) -{ - ethernetext_add_multicast_group(addr); -} - -void RZ_A1_EMAC::remove_multicast_group(const uint8_t *addr) -{ - ethernetext_remove_multicast_group(addr); -} - -void RZ_A1_EMAC::set_all_multicast(bool all) -{ - ethernetext_set_all_multicast(all); -} - -void RZ_A1_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - - -void RZ_A1_EMAC::_recv_callback(void) { - get_instance().recv_callback(); -} - -void RZ_A1_EMAC::recv_callback(void) { - recvThread.flags_set(1); -} - -void RZ_A1_EMAC::recv_task(void) { - uint16_t recv_size; - emac_mem_buf_t *buf; - int cnt; - - while (1) { - rtos::ThisThread::flags_wait_all(1); - for (cnt = 0; cnt < 16; cnt++) { - recv_size = rza1_ethernet_receive(); - if (recv_size == 0) { - break; - } - buf = memory_manager->alloc_heap(recv_size, 0); - if (buf != NULL) { - (void)rza1_ethernet_read((char *)memory_manager->get_ptr(buf), memory_manager->get_len(buf)); - emac_link_input_cb(buf); - } - } - } -} - -void RZ_A1_EMAC::phy_task(void) -{ - if (rza1_ethernet_link() == 1) { - int link_mode = ethernetext_chk_link_mode(); - if (link_mode != link_mode_last) { - if (connect_sts != false) { - emac_link_state_cb(false); - } - if (link_mode != NEGO_FAIL) { - ethernetext_set_link_mode(link_mode); - emac_link_state_cb(true); - connect_sts = true; - } - link_mode_last = link_mode; - } - } else { - if (connect_sts != false) { - emac_link_state_cb(false); - link_mode_last = NEGO_FAIL; - connect_sts = false; - } - } -} - diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.h b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.h deleted file mode 100644 index 70f5507..0000000 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_emac.h +++ /dev/null @@ -1,169 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RZ_A1_EMAC_H -#define RZ_A1_EMAC_H - -#include "EMAC.h" -#include "rtos/Thread.h" - -class RZ_A1_EMAC : public EMAC { -public: - RZ_A1_EMAC(); - - static RZ_A1_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - -private: - EMACMemoryManager *memory_manager; /**< Memory manager */ - uint8_t hwaddr[6]; - bool hwaddr_set; - bool power_on; - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - bool connect_sts; - int link_mode_last; - rtos::Thread recvThread; - int phy_task_handle; /**< Handle for phy task event */ - - static void _recv_callback(void); - void recv_callback(void); - void recv_task(void); - void phy_task(void); - -}; - -#endif /* RZ_A1_EMAC_H */ diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.c b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.c deleted file mode 100644 index 3777327..0000000 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.c +++ /dev/null @@ -1,793 +0,0 @@ -/* Copyright (c) 2020 Renesas Electronics Corporation. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include -#include "rza1_eth.h" -#include "cmsis.h" -#include "mbed_interface.h" -#include "mbed_toolchain.h" -#include "mbed_error.h" -#include "iodefine.h" -#include "rza1_eth_ext.h" - -#if DEVICE_ETHERNET - -/* Descriptor info */ -#define NUM_OF_TX_DESCRIPTOR (16) -#define NUM_OF_RX_DESCRIPTOR (16) -#define SIZE_OF_BUFFER (1600) /* Must be an integral multiple of 32 */ -#define MAX_SEND_SIZE (1514) -/* Ethernet Descriptor Value Define */ -#define TD0_TFP_TOP_BOTTOM (0x30000000) -#define TD0_TACT (0x80000000) -#define TD0_TDLE (0x40000000) -#define RD0_RACT (0x80000000) -#define RD0_RDLE (0x40000000) -#define RD0_RFE (0x08000000) -#define RD0_RCSE (0x04000000) -#define RD0_RFS (0x03FF0000) -#define RD0_RCS (0x0000FFFF) -#define RD0_RFS_RFOF (0x02000000) -#define RD0_RFS_RUAF (0x00400000) -#define RD0_RFS_RRF (0x00100000) -#define RD0_RFS_RTLF (0x00080000) -#define RD0_RFS_RTSF (0x00040000) -#define RD0_RFS_PRE (0x00020000) -#define RD0_RFS_CERF (0x00010000) -#define RD0_RFS_ERROR (RD0_RFS_RFOF | RD0_RFS_RUAF | RD0_RFS_RRF | RD0_RFS_RTLF | \ - RD0_RFS_RTSF | RD0_RFS_PRE | RD0_RFS_CERF) -#define RD1_RDL_MSK (0x0000FFFF) -/* PHY Register */ -#define BASIC_MODE_CONTROL_REG (0) -#define BASIC_MODE_STATUS_REG (1) -#define PHY_IDENTIFIER1_REG (2) -#define PHY_IDENTIFIER2_REG (3) -#define PHY_SP_CTL_STS_REG (31) -/* MII management interface access */ -#define PHY_ADDR (0) /* Confirm the pin connection of the PHY-LSI */ -#define PHY_ST (1) -#define PHY_WRITE (1) -#define PHY_READ (2) -#define MDC_WAIT (6) /* 400ns/4 */ -#define BASIC_STS_MSK_LINK (0x0004) /* Link Status */ -#define BASIC_STS_MSK_AUTO_CMP (0x0020) /* Auto-Negotiate Complete */ -#define M_PHY_ID (0xFFFFFFF0) -#define PHY_ID_LAN8710A (0x0007C0F0) -/* ETHERPIR0 */ -#define PIR0_MDI (0x00000008) -#define PIR0_MDO (0x00000004) -#define PIR0_MMD (0x00000002) -#define PIR0_MDC (0x00000001) -#define PIR0_MDC_HIGH (0x00000001) -#define PIR0_MDC_LOW (0x00000000) -/* ETHEREDRRR0 */ -#define EDRRR0_RR (0x00000001) -/* ETHEREDTRR0 */ -#define EDTRR0_TR (0x00000003) -/* software wait */ -#define LOOP_100us (6700) /* Loop counter for software wait 6666=100us/((1/400MHz)*6cyc) */ - -#define EDMAC_EESIPR_INI_RECV (0x0205001F) /* 0x02000000 : Detect reception suspended */ - /* 0x00040000 : Detect frame reception */ - /* 0x00010000 : Receive FIFO overflow */ - /* 0x00000010 : Residual bit frame reception */ - /* 0x00000008 : Long frame reception */ - /* 0x00000004 : Short frame reception */ - /* 0x00000002 : PHY-LSI reception error */ - /* 0x00000001 : Receive frame CRC error */ -#define EDMAC_EESIPR_INI_EtherC (0x00400000) /* 0x00400000 : E-MAC status register */ - -void rza1_ethernet_address(char *); -void rza1_ethernet_set_link(int, int); - - -/* Send descriptor */ -typedef struct tag_edmac_send_desc { - uint32_t td0; - uint32_t td1; - uint8_t *td2; - uint32_t padding4; -} edmac_send_desc_t; - -/* Receive descriptor */ -typedef struct tag_edmac_recv_desc { - uint32_t rd0; - uint32_t rd1; - uint8_t *rd2; - uint32_t padding4; -} edmac_recv_desc_t; - -/* memory */ -/* The whole transmit/receive descriptors (must be allocated in 16-byte boundaries) */ -/* Transmit/receive buffers (must be allocated in 16-byte boundaries) */ -#if defined(__ICCARM__) -#pragma data_alignment=16 -static uint8_t rza1_ethernet_nc_memory[(sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR) + - (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR) + - (NUM_OF_TX_DESCRIPTOR * SIZE_OF_BUFFER) + - (NUM_OF_RX_DESCRIPTOR * SIZE_OF_BUFFER)] //16 bytes aligned! - @ ".mirrorram"; -#else -static uint8_t rza1_ethernet_nc_memory[(sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR) + - (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR) + - (NUM_OF_TX_DESCRIPTOR * SIZE_OF_BUFFER) + - (NUM_OF_RX_DESCRIPTOR * SIZE_OF_BUFFER)] - __attribute((section("NC_BSS"),aligned(16))); //16 bytes aligned! -#endif -static int32_t rx_read_offset; /* read offset */ -static int32_t tx_wite_offset; /* write offset */ -static uint32_t send_top_index; -static uint32_t recv_top_index; -static int32_t Interrupt_priority; -static edmac_send_desc_t *p_eth_desc_dsend = NULL; -static edmac_recv_desc_t *p_eth_desc_drecv = NULL; -static edmac_recv_desc_t *p_recv_end_desc = NULL; -static ethernetext_cb_fnc *p_recv_cb_fnc = NULL; -static char mac_addr[6] = {0x00, 0x02, 0xF7, 0xF0, 0x00, 0x00}; /* MAC Address */ -static uint32_t phy_id = 0; -static uint32_t start_stop = 1; /* 0:stop 1:start */ -static uint32_t tsu_ten_tmp = 0; - -volatile struct st_ether_from_tsu_adrh0* ETHER_FROM_TSU_ADRH0_ARRAY[ ETHER_FROM_TSU_ADRH0_ARRAY_COUNT ] = - /* ->MISRA 11.3 */ /* ->SEC R2.7.1 */ - ETHER_FROM_TSU_ADRH0_ARRAY_ADDRESS_LIST; - /* <-MISRA 11.3 */ /* <-SEC R2.7.1 */ - -/* function */ -static void lan_reg_reset(void); -static void lan_desc_create(void); -static void lan_reg_set(int32_t link); -static uint16_t phy_reg_read(uint16_t reg_addr); -static void phy_reg_write(uint16_t reg_addr, uint16_t data); -static void mii_preamble(void); -static void mii_cmd(uint16_t reg_addr, uint32_t option); -static void mii_reg_read(uint16_t *data); -static void mii_reg_write(uint16_t data); -static void mii_z(void); -static void mii_write_1(void); -static void mii_write_0(void); -static void set_ether_pir(uint32_t set_data); -static void wait_100us(int32_t wait_cnt); - - -int ethernetext_init(rza1_ethernet_cfg_t *p_ethcfg) { - int32_t i; - uint16_t val; - - CPGSTBCR7 &= ~(CPG_STBCR7_BIT_MSTP74); /* enable ETHER clock */ - -#if defined(TARGET_RZ_A1H) - /* P4_2(PHY Reset) */ - GPIOP4 &= ~0x0004; /* Outputs low level */ - GPIOPMC4 &= ~0x0004; /* Port mode */ - GPIOPM4 &= ~0x0004; /* Output mode */ - - /* GPIO P1 P1_14(ET_COL) */ - GPIOPMC1 |= 0x4000; - GPIOPFCAE1 &= ~0x4000; - GPIOPFCE1 |= 0x4000; - GPIOPFC1 |= 0x4000; - - /* P3_0(ET_TXCLK), P3_3(ET_MDIO), P3_4(ET_RXCLK), P3_5(ET_RXER), P3_6(ET_RXDV) */ - GPIOPMC3 |= 0x0079; - GPIOPFCAE3 &= ~0x0079; - GPIOPFCE3 &= ~0x0079; - GPIOPFC3 |= 0x0079; - GPIOPIPC3 |= 0x0079; - - /* P5_9(ET_MDC) */ - GPIOPMC5 |= 0x0200; - GPIOPFCAE5 &= ~0x0200; - GPIOPFCE5 &= ~0x0200; - GPIOPFC5 |= 0x0200; - GPIOPIPC5 |= 0x0200; - - /* P10_1(ET_TXER), P10_2(ET_TXEN), P10_3(ET_CRS), P10_4(ET_TXD0), P10_5(ET_TXD1) */ - /* P10_6(ET_TXD2), P10_7(ET_TXD3), P10_8(ET_RXD0), P10_9(ET_RXD1), P10_10(ET_RXD2), P10_11(ET_RXD3) */ - GPIOPMC10 |= 0x0FFE; - GPIOPFCAE10 &= ~0x0FFE; - GPIOPFCE10 |= 0x0FFE; - GPIOPFC10 |= 0x0FFE; - GPIOPIPC10 |= 0x0FFE; - - /* Resets the E-MAC,E-DMAC */ - lan_reg_reset(); - - /* PHY Reset */ - GPIOP4 &= ~0x0004; /* P4_2 Outputs low level */ - wait_100us(250); /* 25msec */ - GPIOP4 |= 0x0004; /* P4_2 Outputs high level */ - wait_100us(100); /* 10msec */ -#else -#error "There is no initialization processing." -#endif - - /* Resets the PHY-LSI */ - phy_reg_write(BASIC_MODE_CONTROL_REG, 0x8000); - for (i = 10000; i > 0; i--) { - val = phy_reg_read(BASIC_MODE_CONTROL_REG); - if (((uint32_t)val & 0x8000uL) == 0) { - break; /* Reset complete */ - } - } - - phy_id = ((uint32_t)phy_reg_read(PHY_IDENTIFIER1_REG) << 16) - | (uint32_t)phy_reg_read(PHY_IDENTIFIER2_REG); - - Interrupt_priority = p_ethcfg->int_priority; - p_recv_cb_fnc = p_ethcfg->recv_cb; - start_stop = 1; - - if (p_ethcfg->ether_mac != NULL) { - (void)memcpy(mac_addr, p_ethcfg->ether_mac, sizeof(mac_addr)); - } else { - rza1_ethernet_address(mac_addr); /* Get MAC Address */ - } - - return 0; -} - -void ethernetext_start_stop(int32_t mode) { - if (mode == 1) { - /* start */ - ETHEREDTRR0 |= EDTRR0_TR; - ETHEREDRRR0 |= EDRRR0_RR; - start_stop = 1; - } else { - /* stop */ - ETHEREDTRR0 &= ~EDTRR0_TR; - ETHEREDRRR0 &= ~EDRRR0_RR; - start_stop = 0; - } -} - -int ethernetext_chk_link_mode(void) { - int32_t link; - uint16_t data; - - if ((phy_id & M_PHY_ID) == PHY_ID_LAN8710A) { - data = phy_reg_read(PHY_SP_CTL_STS_REG); - switch (((uint32_t)data >> 2) & 0x00000007) { - case 0x0001: - link = HALF_10M; - break; - case 0x0005: - link = FULL_10M; - break; - case 0x0002: - link = HALF_TX; - break; - case 0x0006: - link = FULL_TX; - break; - default: - link = NEGO_FAIL; - break; - } - } else { - link = NEGO_FAIL; - } - - return link; -} - -void ethernetext_set_link_mode(int32_t link) { - lan_reg_reset(); /* Resets the E-MAC,E-DMAC */ - lan_desc_create(); /* Initialize of buffer memory */ - lan_reg_set(link); /* E-DMAC, E-MAC initialization */ -} - -void ethernetext_add_multicast_group(const uint8_t *addr) { - uint32_t cnt; - uint32_t tmp_data_h; - uint32_t tmp_data_l; - - if (tsu_ten_tmp == 0xFFFFFFFF) { - ethernetext_set_all_multicast(1); - } else { - tmp_data_h = ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]); - tmp_data_l = ((uint32_t)addr[4] << 8) | ((uint32_t)addr[5]); - - for (cnt = 0; cnt < 32; cnt++) { - if ((tsu_ten_tmp & (0x80000000 >> cnt)) == 0) { - while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { - ; - } - ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 = tmp_data_h; - while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { - ; - } - ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 = tmp_data_l; - if ((ETHERECMR0 & 0x00002000) != 0) { - ETHERTSU_TEN |= (0x80000000 >> cnt); - } - tsu_ten_tmp |= (0x80000000 >> cnt); - break; - } - } - } -} - -void ethernetext_remove_multicast_group(const uint8_t *addr) { - uint32_t cnt; - uint32_t tmp_data_h; - uint32_t tmp_data_l; - - tmp_data_h = ((uint32_t)addr[0] << 24) | ((uint32_t)addr[1] << 16) | ((uint32_t)addr[2] << 8) | ((uint32_t)addr[3]); - tmp_data_l = ((uint32_t)addr[4] << 8) | ((uint32_t)addr[5]); - - for (cnt = 0; cnt< 32; cnt++) { - if ((ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 == tmp_data_h) && - (ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 == tmp_data_l)) { - while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { - ; - } - ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRH0 = 0; - while ((ETHERTSU_ADSBSY & 0x00000001) != 0) { - ; - } - ETHER_FROM_TSU_ADRH0_ARRAY[cnt]->TSU_ADRL0 = 0; - - ETHERTSU_TEN &= ~(0x80000000 >> cnt); - tsu_ten_tmp &= ~(0x80000000 >> cnt); - break; - } - } -} - -void ethernetext_set_all_multicast(int all) { - if (all != 0) { - ETHERECMR0 &= ~(0x00002000); - ETHERTSU_TEN = 0x00000000; - } else { - ETHERECMR0 |= 0x00002000; - ETHERTSU_TEN = tsu_ten_tmp; - } -} - - -int rza1_ethernet_init() { - rza1_ethernet_cfg_t ethcfg; - - ethcfg.int_priority = 5; - ethcfg.recv_cb = NULL; - ethcfg.ether_mac = NULL; - ethernetext_init(ðcfg); - rza1_ethernet_set_link(-1, 0); /* Auto-Negotiation */ - - return 0; -} - -void rza1_ethernet_free() { - ETHERARSTR |= 0x00000001; /* ETHER software reset */ - CPGSTBCR7 |= CPG_STBCR7_BIT_MSTP74; /* disable ETHER clock */ -} - -int rza1_ethernet_write(const char *data, int slen) { - edmac_send_desc_t *p_send_desc; - int32_t copy_size; - - if ((p_eth_desc_dsend == NULL) || (data == NULL) || (slen < 0) - || (tx_wite_offset < 0) || (tx_wite_offset >= MAX_SEND_SIZE)) { - copy_size = 0; - } else { - p_send_desc = &p_eth_desc_dsend[send_top_index]; /* Current descriptor */ - if ((p_send_desc->td0 & TD0_TACT) != 0) { - copy_size = 0; - } else { - copy_size = MAX_SEND_SIZE - tx_wite_offset; - if (copy_size > slen) { - copy_size = slen; - } - (void)memcpy(&p_send_desc->td2[tx_wite_offset], data, copy_size); - tx_wite_offset += copy_size; - } - } - - return copy_size; -} - -int rza1_ethernet_send() { - edmac_send_desc_t *p_send_desc; - int32_t ret; - - if ((p_eth_desc_dsend == NULL) || (tx_wite_offset <= 0)) { - ret = 0; - } else { - /* Transfer 1 frame */ - p_send_desc = &p_eth_desc_dsend[send_top_index]; /* Current descriptor */ - - /* Sets the frame length */ - p_send_desc->td1 = ((uint32_t)tx_wite_offset << 16); - tx_wite_offset = 0; - - /* Sets the transmit descriptor to transmit again */ - p_send_desc->td0 &= (TD0_TACT | TD0_TDLE | TD0_TFP_TOP_BOTTOM); - p_send_desc->td0 |= TD0_TACT; - if ((start_stop == 1) && ((ETHEREDTRR0 & EDTRR0_TR) != EDTRR0_TR)) { - ETHEREDTRR0 |= EDTRR0_TR; - } - - /* Update the current descriptor */ - send_top_index++; - if (send_top_index >= NUM_OF_TX_DESCRIPTOR) { - send_top_index = 0; - } - ret = 1; - } - - return ret; -} - -int rza1_ethernet_receive() { - edmac_recv_desc_t *p_recv_desc; - int32_t receive_size = 0; - - if (p_eth_desc_drecv != NULL) { - if (p_recv_end_desc != NULL) { - /* Sets the receive descriptor to receive again */ - p_recv_end_desc->rd0 &= (RD0_RACT | RD0_RDLE); - p_recv_end_desc->rd0 |= RD0_RACT; - if ((start_stop == 1) && ((ETHEREDRRR0 & EDRRR0_RR) == 0)) { - ETHEREDRRR0 |= EDRRR0_RR; - } - p_recv_end_desc = NULL; - } - - p_recv_desc = &p_eth_desc_drecv[recv_top_index]; /* Current descriptor */ - if ((p_recv_desc->rd0 & RD0_RACT) == 0) { - /* Receives 1 frame */ - if (((p_recv_desc->rd0 & RD0_RFE) != 0) && ((p_recv_desc->rd0 & RD0_RFS_ERROR) != 0)) { - /* Receive frame error */ - /* Sets the receive descriptor to receive again */ - p_recv_desc->rd0 &= (RD0_RACT | RD0_RDLE); - p_recv_desc->rd0 |= RD0_RACT; - if ((start_stop == 1) && ((ETHEREDRRR0 & EDRRR0_RR) == 0)) { - ETHEREDRRR0 |= EDRRR0_RR; - } - } else { - /* Copies the received frame */ - rx_read_offset = 0; - p_recv_end_desc = p_recv_desc; - receive_size = (p_recv_desc->rd1 & RD1_RDL_MSK); /* number of bytes received */ - } - - /* Update the current descriptor */ - recv_top_index++; - if (recv_top_index >= NUM_OF_TX_DESCRIPTOR) { - recv_top_index = 0; - } - } - } - - return receive_size; -} - -int rza1_ethernet_read(char *data, int dlen) { - edmac_recv_desc_t *p_recv_desc = p_recv_end_desc; /* Read top descriptor */ - int32_t copy_size; - - if ((data == NULL) || (dlen < 0) || (p_recv_desc == NULL)) { - copy_size = 0; - } else { - copy_size = (p_recv_desc->rd1 & RD1_RDL_MSK) - rx_read_offset; - if (copy_size > dlen) { - copy_size = dlen; - } - (void)memcpy(data, &p_recv_desc->rd2[rx_read_offset], (size_t)copy_size); - rx_read_offset += copy_size; - } - - return copy_size; -} - -void rza1_ethernet_address(char *mac) { - if (mac != NULL) { - mbed_mac_address(mac); /* Get MAC Address */ - } -} - -int rza1_ethernet_link(void) { - int32_t ret; - uint16_t data; - - data = phy_reg_read(BASIC_MODE_STATUS_REG); - if (((uint32_t)data & BASIC_STS_MSK_LINK) != 0) { - ret = 1; - } else { - ret = 0; - } - - return ret; -} - -void rza1_ethernet_set_link(int speed, int duplex) { - uint16_t data; - int32_t i; - int32_t link; - - if ((speed < 0) || (speed > 1)) { - data = 0x1000; /* Auto-Negotiation Enable */ - phy_reg_write(BASIC_MODE_CONTROL_REG, data); - for (i = 0; i < 1000; i++) { - data = phy_reg_read(BASIC_MODE_STATUS_REG); - if (((uint32_t)data & BASIC_STS_MSK_AUTO_CMP) != 0) { - break; - } - wait_100us(10); - } - } else { - data = (uint16_t)(((uint32_t)speed << 13) | ((uint32_t)duplex << 8)); - phy_reg_write(BASIC_MODE_CONTROL_REG, data); - wait_100us(1); - } - - link = ethernetext_chk_link_mode(); - ethernetext_set_link_mode(link); -} - -void INT_Ether(void) { - uint32_t stat_edmac; - uint32_t stat_etherc; - - /* Clear the interrupt request flag */ - stat_edmac = (ETHEREESR0 & ETHEREESIPR0); /* Targets are restricted to allowed interrupts */ - ETHEREESR0 = stat_edmac; - /* Reception-related */ - if (stat_edmac & EDMAC_EESIPR_INI_RECV) { - if (p_recv_cb_fnc != NULL) { - p_recv_cb_fnc(); - } - } - /* E-MAC-related */ - if (stat_edmac & EDMAC_EESIPR_INI_EtherC) { - /* Clear the interrupt request flag */ - stat_etherc = (ETHERECSR0 & ETHERECSIPR0); /* Targets are restricted to allowed interrupts */ - ETHERECSR0 = stat_etherc; - } -} - -static void lan_reg_reset(void) { - volatile int32_t j = 400; /* Wait for B dia 256 cycles ((I dia/B dia)*256)/6cyc = 8*256/6 = 342 */ - - ETHERARSTR |= 0x00000001; /* ETHER software reset */ - while (j--) { - /* Do Nothing */ - } - - ETHEREDSR0 |= 0x00000003; /* E-DMAC software reset */ - ETHEREDMR0 |= 0x00000003; /* Set SWRR and SWRT simultaneously */ - - /* Check clear software reset */ - while ((ETHEREDMR0 & 0x00000003) != 0) { - /* Do Nothing */ - } -} - -static void lan_desc_create(void) { - int32_t i; - uint8_t *p_memory_top; - - (void)memset((void *)rza1_ethernet_nc_memory, 0, sizeof(rza1_ethernet_nc_memory)); - p_memory_top = rza1_ethernet_nc_memory; - - /* Descriptor area configuration */ - p_eth_desc_dsend = (edmac_send_desc_t *)p_memory_top; - p_memory_top += (sizeof(edmac_send_desc_t) * NUM_OF_TX_DESCRIPTOR); - p_eth_desc_drecv = (edmac_recv_desc_t *)p_memory_top; - p_memory_top += (sizeof(edmac_recv_desc_t) * NUM_OF_RX_DESCRIPTOR); - - /* Transmit descriptor */ - for (i = 0; i < NUM_OF_TX_DESCRIPTOR; i++) { - p_eth_desc_dsend[i].td2 = p_memory_top; /* TD2 TBA */ - p_memory_top += SIZE_OF_BUFFER; - p_eth_desc_dsend[i].td1 = 0; /* TD1 TDL */ - p_eth_desc_dsend[i].td0 = TD0_TFP_TOP_BOTTOM; /* TD0:1frame/1buf1buf, transmission disabled */ - } - p_eth_desc_dsend[i - 1].td0 |= TD0_TDLE; /* Set the last descriptor */ - - /* Receive descriptor */ - for (i = 0; i < NUM_OF_RX_DESCRIPTOR; i++) { - p_eth_desc_drecv[i].rd2 = p_memory_top; /* RD2 RBA */ - p_memory_top += SIZE_OF_BUFFER; - p_eth_desc_drecv[i].rd1 = ((uint32_t)SIZE_OF_BUFFER << 16); /* RD1 RBL */ - p_eth_desc_drecv[i].rd0 = RD0_RACT; /* RD0:reception enabled */ - } - p_eth_desc_drecv[i - 1].rd0 |= RD0_RDLE; /* Set the last descriptor */ - - /* Initialize descriptor management information */ - send_top_index = 0; - recv_top_index = 0; - rx_read_offset = 0; - tx_wite_offset = 0; - p_recv_end_desc = NULL; -} - -static void lan_reg_set(int32_t link) { - /* MAC address setting */ - ETHERMAHR0 = ((uint8_t)mac_addr[0] << 24) - | ((uint8_t)mac_addr[1] << 16) - | ((uint8_t)mac_addr[2] << 8) - | (uint8_t)mac_addr[3]; - ETHERMALR0 = ((uint8_t)mac_addr[4] << 8) - | (uint8_t)mac_addr[5]; - - /* E-DMAC */ - ETHERTDLAR0 = (uint32_t)&p_eth_desc_dsend[0]; - ETHERRDLAR0 = (uint32_t)&p_eth_desc_drecv[0]; - ETHERTDFAR0 = (uint32_t)&p_eth_desc_dsend[0]; - ETHERRDFAR0 = (uint32_t)&p_eth_desc_drecv[0]; - ETHERTDFXR0 = (uint32_t)&p_eth_desc_dsend[NUM_OF_TX_DESCRIPTOR - 1]; - ETHERRDFXR0 = (uint32_t)&p_eth_desc_drecv[NUM_OF_RX_DESCRIPTOR - 1]; - ETHERTDFFR0 |= 0x00000001; /* TDLF Transmit Descriptor Queue Last Flag : Last descriptor (1) */ - ETHERRDFFR0 |= 0x00000001; /* RDLF Receive Descriptor Queue Last Flag : Last descriptor (1) */ - ETHEREDMR0 |= 0x00000040; /* Little endian */ - ETHERTRSCER0 &= ~0x0003009F; /* All clear */ - ETHERTFTR0 &= ~0x000007FF; /* TFT[10:0] Transmit FIFO Threshold : Store and forward modes (H'000) */ - ETHERFDR0 |= 0x00000707; /* Transmit FIFO Size:2048 bytes, Receive FIFO Size:2048 bytes */ - ETHERRMCR0 |= 0x00000001; /* RNC Receive Enable Control : Continuous reception enabled (1) */ - ETHERFCFTR0 &= ~0x001F00FF; - ETHERFCFTR0 |= 0x00070007; - ETHERRPADIR0 &= ~0x001FFFFF; /* Padding Size:No padding insertion, Padding Slot:Inserts at first byte */ - - /* E-MAC */ - ETHERECMR0 &= ~0x04BF2063; /* All clear */ - ETHERRFLR0 &= ~0x0003FFFF; /* RFL[17:0] Receive Frame Length : 1518 bytes (H'00000) */ - ETHERAPR0 &= ~0x0000FFFF; /* AP[15:0] Automatic PAUSE : Flow control is disabled (H'0000) */ - ETHERMPR0 &= ~0x0000FFFF; /* MP[15:0] Manual PAUSE : Flow control is disabled (H'0000) */ - ETHERTPAUSER0 &= ~0x0000FFFF; /* Upper Limit for Automatic PAUSE Frame : Retransmit count is unlimited */ - ETHERCSMR &= ~0xC000003F; /* The result of checksum is not written back to the receive descriptor */ - if ((link == FULL_TX) || (link == FULL_10M) || (link == NEGO_FAIL)) { - ETHERECMR0 |= 0x00000002; /* Set to full-duplex mode */ - } else { - ETHERECMR0 &= ~0x00000002; /* Set to half-duplex mode */ - } - ETHERECMR0 |= 0x00002000; /* MCT = 1 */ - - /* Interrupt-related */ - if (p_recv_cb_fnc != NULL) { - ETHEREESR0 |= 0xFF7F009F; /* Clear all status (by writing 1) */ - ETHEREESIPR0 |= 0x00040000; /* FR Frame Reception (1) */ - ETHERECSR0 |= 0x00000011; /* Clear all status (clear by writing 1) */ - ETHERECSIPR0 &= ~0x00000011; /* PFROIP Disable, ICDIP Disable */ - InterruptHandlerRegister(ETHERI_IRQn, INT_Ether); /* Ethernet interrupt handler registration */ - GIC_SetPriority(ETHERI_IRQn, Interrupt_priority); /* Ethernet interrupt priority */ - GIC_SetConfiguration(ETHERI_IRQn, 1); - GIC_EnableIRQ(ETHERI_IRQn); /* Enables the E-DMAC interrupt */ - } - - ETHERECMR0 |= 0x00000060; /* RE Enable, TE Enable */ - - /* Enable transmission/reception */ - if ((start_stop == 1) && ((ETHEREDRRR0 & 0x00000001) == 0)) { - ETHEREDRRR0 |= 0x00000001; /* RR */ - } -} - -static uint16_t phy_reg_read(uint16_t reg_addr) { - uint16_t data; - - mii_preamble(); - mii_cmd(reg_addr, PHY_READ); - mii_z(); - mii_reg_read(&data); - mii_z(); - - return data; -} - -static void phy_reg_write(uint16_t reg_addr, uint16_t data) { - mii_preamble(); - mii_cmd(reg_addr, PHY_WRITE); - mii_write_1(); - mii_write_0(); - mii_reg_write(data); - mii_z(); -} - -static void mii_preamble(void) { - int32_t i = 32; - - for (i = 32; i > 0; i--) { - /* 1 is output via the MII (Media Independent Interface) block. */ - mii_write_1(); - } -} - -static void mii_cmd(uint16_t reg_addr, uint32_t option) { - int32_t i; - uint16_t data = 0; - - data |= (PHY_ST << 14); /* ST code */ - data |= (option << 12); /* OP code */ - data |= (PHY_ADDR << 7); /* PHY Address */ - data |= (uint16_t)(reg_addr << 2); /* Reg Address */ - for (i = 14; i > 0; i--) { - if ((data & 0x8000) == 0) { - mii_write_0(); - } else { - mii_write_1(); - } - data <<= 1; - } -} - -static void mii_reg_read(uint16_t *data) { - int32_t i; - uint16_t reg_data = 0; - - /* Data are read in one bit at a time */ - for (i = 16; i > 0; i--) { - set_ether_pir(PIR0_MDC_LOW); - set_ether_pir(PIR0_MDC_HIGH); - reg_data <<= 1; - reg_data |= (uint16_t)((ETHERPIR0 & PIR0_MDI) >> 3); /* MDI read */ - set_ether_pir(PIR0_MDC_HIGH); - set_ether_pir(PIR0_MDC_LOW); - } - *data = reg_data; -} - -static void mii_reg_write(uint16_t data) { - int32_t i; - - /* Data are written one bit at a time */ - for (i = 16; i > 0; i--) { - if ((data & 0x8000) == 0) { - mii_write_0(); - } else { - mii_write_1(); - } - data <<= 1; - } -} - -static void mii_z(void) { - set_ether_pir(PIR0_MDC_LOW); - set_ether_pir(PIR0_MDC_HIGH); - set_ether_pir(PIR0_MDC_HIGH); - set_ether_pir(PIR0_MDC_LOW); -} - -static void mii_write_1(void) { - set_ether_pir(PIR0_MDO | PIR0_MMD); - set_ether_pir(PIR0_MDO | PIR0_MMD | PIR0_MDC); - set_ether_pir(PIR0_MDO | PIR0_MMD | PIR0_MDC); - set_ether_pir(PIR0_MDO | PIR0_MMD); -} - -static void mii_write_0(void) { - set_ether_pir(PIR0_MMD); - set_ether_pir(PIR0_MMD | PIR0_MDC); - set_ether_pir(PIR0_MMD | PIR0_MDC); - set_ether_pir(PIR0_MMD); -} - -static void set_ether_pir(uint32_t set_data) { - int32_t i; - - for (i = MDC_WAIT; i > 0; i--) { - ETHERPIR0 = set_data; - } -} - -static void wait_100us(int32_t wait_cnt) { - volatile int32_t j = LOOP_100us * wait_cnt; - - while (--j) { - /* Do Nothing */ - } -} -#endif /* DEVICE_ETHERNET */ diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.h b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.h deleted file mode 100644 index 3553879..0000000 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright (c) 2020 Renesas Electronics Corporation. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBED_ETHERNET_API_H -#define MBED_ETHERNET_API_H - -#include "device.h" -#include "platform/mbed_toolchain.h" - -#if DEVICE_ETHERNET - -#ifdef __cplusplus -extern "C" { -#endif - -// Connection constants -int rza1_ethernet_init(void); -void rza1_ethernet_free(void); - -// write size bytes from data to ethernet buffer -// return num bytes written -// or -1 if size is too big -int rza1_ethernet_write(const char *data, int size); - -// send ethernet write buffer, returning the packet size sent -int rza1_ethernet_send(void); - -// receive from ethernet buffer, returning packet size, or 0 if no packet -int rza1_ethernet_receive(void); - -// read size bytes in to data, return actual num bytes read (0..size) -// if data == NULL, throw the bytes away -int rza1_ethernet_read(char *data, int size); - -// get the ethernet address -void rza1_ethernet_address(char *mac); - -// see if the link is up -int rza1_ethernet_link(void); - -// force link settings -void rza1_ethernet_set_link(int speed, int duplex); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif - - -/** @}*/ diff --git a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth_ext.h b/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth_ext.h deleted file mode 100644 index e61a15f..0000000 --- a/features/netsocket/emac-drivers/TARGET_RZ_A1_EMAC/rza1_eth_ext.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (c) 2020 Renesas Electronics Corporation. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef ETHERNETEXT_H -#define ETHERNETEXT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* PHY link mode */ -#define NEGO_FAIL (0) -#define HALF_10M (1) -#define FULL_10M (2) -#define HALF_TX (3) -#define FULL_TX (4) - -typedef void (ethernetext_cb_fnc)(void); - -typedef struct tag_rza1_ethernet_cfg { - int int_priority; - ethernetext_cb_fnc *recv_cb; - char *ether_mac; -} rza1_ethernet_cfg_t; - -extern int ethernetext_init(rza1_ethernet_cfg_t *p_ethcfg); -extern void ethernetext_start_stop(int32_t mode); -extern int ethernetext_chk_link_mode(void); -extern void ethernetext_set_link_mode(int32_t link); -extern void ethernetext_add_multicast_group(const uint8_t *addr); -extern void ethernetext_remove_multicast_group(const uint8_t *addr); -extern void ethernetext_set_all_multicast(int all); -#ifdef __cplusplus -} -#endif - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c deleted file mode 100644 index 7b054c7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/TARGET_NUCLEO_F207ZG/stm32f2_eth_init.c +++ /dev/null @@ -1,119 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f2xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c deleted file mode 100644 index dd004db..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32f2_eth_conf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stm32f2xx_hal.h" - -void _eth_config_mac(ETH_HandleTypeDef *heth) -{ - ETH_MACInitTypeDef macconf = { - .Watchdog = ETH_WATCHDOG_ENABLE, - .Jabber = ETH_JABBER_ENABLE, - .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, - .CarrierSense = ETH_CARRIERSENCE_ENABLE, - .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, - .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, - .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, - .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, - .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, - .BackOffLimit = ETH_BACKOFFLIMIT_10, - .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, - .ReceiveAll = ETH_RECEIVEAll_DISABLE, - .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, - .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, - .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, - .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, - .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, - .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter - .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, - .HashTableHigh = 0x0U, - .HashTableLow = 0x0U, - .PauseTime = 0x0U, - .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, - .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, - .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, - .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, - .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, - .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, - .VLANTagIdentifier = 0x0U - }; - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; - } else { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; - } - - (void) HAL_ETH_ConfigMAC(heth, &macconf); -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h deleted file mode 100644 index c4fe5e7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F2/stm32xx_emac_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32XX_EMAC_CONFIG_H__ -#define STM32XX_EMAC_CONFIG_H__ - -#define ETH_IP_VERSION_V1 - -#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c deleted file mode 100644 index a11be4a..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_conf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stm32f4xx_hal.h" - -void _eth_config_mac(ETH_HandleTypeDef *heth) -{ - ETH_MACInitTypeDef macconf = { - .Watchdog = ETH_WATCHDOG_ENABLE, - .Jabber = ETH_JABBER_ENABLE, - .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, - .CarrierSense = ETH_CARRIERSENCE_ENABLE, - .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, - .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, - .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, - .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, - .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, - .BackOffLimit = ETH_BACKOFFLIMIT_10, - .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, - .ReceiveAll = ETH_RECEIVEAll_DISABLE, - .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, - .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, - .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, - .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, - .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, - .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter - .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, - .HashTableHigh = 0x0U, - .HashTableLow = 0x0U, - .PauseTime = 0x0U, - .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, - .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, - .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, - .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, - .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, - .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, - .VLANTagIdentifier = 0x0U, - }; - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; - } else { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; - } - - (void) HAL_ETH_ConfigMAC(heth, &macconf); -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c deleted file mode 100644 index a95ea0f..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_ARCH_MAX/stm32f4_eth_init.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "stm32f4xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> - RMII_MII_TX_EN --------------------> PB11 - RMII_MII_TXD0 ---------------------> PB12 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB11, PB12 and PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> - RMII_MII_TX_EN --------------------> PB11 - RMII_MII_TXD0 ---------------------> PB12 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c deleted file mode 100644 index a11be4a..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_conf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stm32f4xx_hal.h" - -void _eth_config_mac(ETH_HandleTypeDef *heth) -{ - ETH_MACInitTypeDef macconf = { - .Watchdog = ETH_WATCHDOG_ENABLE, - .Jabber = ETH_JABBER_ENABLE, - .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, - .CarrierSense = ETH_CARRIERSENCE_ENABLE, - .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, - .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, - .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, - .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, - .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, - .BackOffLimit = ETH_BACKOFFLIMIT_10, - .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, - .ReceiveAll = ETH_RECEIVEAll_DISABLE, - .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, - .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, - .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, - .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, - .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, - .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter - .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, - .HashTableHigh = 0x0U, - .HashTableLow = 0x0U, - .PauseTime = 0x0U, - .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, - .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, - .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, - .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, - .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, - .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, - .VLANTagIdentifier = 0x0U, - }; - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; - } else { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; - } - - (void) HAL_ETH_ConfigMAC(heth, &macconf); -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c deleted file mode 100644 index 09dfb94..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F429ZI/stm32f4_eth_init.c +++ /dev/null @@ -1,119 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f4xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c deleted file mode 100644 index a11be4a..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_conf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stm32f4xx_hal.h" - -void _eth_config_mac(ETH_HandleTypeDef *heth) -{ - ETH_MACInitTypeDef macconf = { - .Watchdog = ETH_WATCHDOG_ENABLE, - .Jabber = ETH_JABBER_ENABLE, - .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, - .CarrierSense = ETH_CARRIERSENCE_ENABLE, - .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, - .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, - .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, - .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, - .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, - .BackOffLimit = ETH_BACKOFFLIMIT_10, - .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, - .ReceiveAll = ETH_RECEIVEAll_DISABLE, - .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, - .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, - .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, - .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, - .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, - .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter - .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, - .HashTableHigh = 0x0U, - .HashTableLow = 0x0U, - .PauseTime = 0x0U, - .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, - .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, - .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, - .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, - .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, - .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, - .VLANTagIdentifier = 0x0U, - }; - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; - } else { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; - } - - (void) HAL_ETH_ConfigMAC(heth, &macconf); -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c deleted file mode 100644 index 09dfb94..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/stm32f4_eth_init.c +++ /dev/null @@ -1,119 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f4xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h deleted file mode 100644 index c4fe5e7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F4/stm32xx_emac_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32XX_EMAC_CONFIG_H__ -#define STM32XX_EMAC_CONFIG_H__ - -#define ETH_IP_VERSION_V1 - -#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c deleted file mode 100644 index b0a2aec..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG/stm32f7_eth_init.c +++ /dev/null @@ -1,115 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f7xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - /* Disable DCache for STM32F7 family */ - SCB_DisableDCache(); - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PG14 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11, PG13 and PG14 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PG14 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c deleted file mode 100644 index de64941..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F769NI/stm32f7_eth_init.c +++ /dev/null @@ -1,121 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f7xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - /* Disable DCache for STM32F7 family */ - SCB_DisableDCache(); - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOD_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PD5 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PG14 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PD5 */ - GPIO_InitStructure.Pin = GPIO_PIN_5; - HAL_GPIO_Init(GPIOD, &GPIO_InitStructure); - - /* Configure PG11, PG13 and PG14 */ - GPIO_InitStructure.Pin = GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PD5 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PG14 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_11 | GPIO_PIN_13 | GPIO_PIN_14); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c deleted file mode 100644 index 019898b..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F746ZG/stm32f7_eth_init.c +++ /dev/null @@ -1,121 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f7xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - /* Disable DCache for STM32F7 family */ - SCB_DisableDCache(); - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c deleted file mode 100644 index 019898b..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F756ZG/stm32f7_eth_init.c +++ /dev/null @@ -1,121 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f7xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - /* Disable DCache for STM32F7 family */ - SCB_DisableDCache(); - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c deleted file mode 100644 index 019898b..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/TARGET_NUCLEO_F767ZI/stm32f7_eth_init.c +++ /dev/null @@ -1,121 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32f7xx_hal.h" - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStructure; - if (heth->Instance == ETH) { - /* Disable DCache for STM32F7 family */ - SCB_DisableDCache(); - - /* Enable GPIOs clocks */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - /* Configure PA1, PA2 and PA7 */ - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Mode = GPIO_MODE_AF_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Alternate = GPIO_AF11_ETH; - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); - - /* Configure PB13 */ - GPIO_InitStructure.Pin = GPIO_PIN_13; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - /* Configure PC1, PC4 and PC5 */ - GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - /* Configure PG2, PG11 and PG13 */ - GPIO_InitStructure.Pin = GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13; - HAL_GPIO_Init(GPIOG, &GPIO_InitStructure); - - /* Enable the Ethernet global Interrupt */ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); - - /* Enable ETHERNET clock */ - __HAL_RCC_ETH_CLK_ENABLE(); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH_CLK_DISABLE(); - - /** ETH GPIO Configuration - RMII_REF_CLK ----------------------> PA1 - RMII_MDIO -------------------------> PA2 - RMII_MDC --------------------------> PC1 - RMII_MII_CRS_DV -------------------> PA7 - RMII_MII_RXD0 ---------------------> PC4 - RMII_MII_RXD1 ---------------------> PC5 - RMII_MII_RXER ---------------------> PG2 - RMII_MII_TX_EN --------------------> PG11 - RMII_MII_TXD0 ---------------------> PG13 - RMII_MII_TXD1 ---------------------> PB13 - */ - HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_7); - HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13); - HAL_GPIO_DeInit(GPIOC, GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5); - HAL_GPIO_DeInit(GPIOG, GPIO_PIN_2 | GPIO_PIN_11 | GPIO_PIN_13); - - /* Disable the Ethernet global Interrupt */ - NVIC_DisableIRQ(ETH_IRQn); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c deleted file mode 100644 index 76dbeb4..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32f7_eth_conf.c +++ /dev/null @@ -1,60 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "stm32f7xx_hal.h" - -void _eth_config_mac(ETH_HandleTypeDef *heth) -{ - ETH_MACInitTypeDef macconf = { - .Watchdog = ETH_WATCHDOG_ENABLE, - .Jabber = ETH_JABBER_ENABLE, - .InterFrameGap = ETH_INTERFRAMEGAP_96BIT, - .CarrierSense = ETH_CARRIERSENCE_ENABLE, - .ReceiveOwn = ETH_RECEIVEOWN_ENABLE, - .LoopbackMode = ETH_LOOPBACKMODE_DISABLE, - .ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE, - .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE, - .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE, - .BackOffLimit = ETH_BACKOFFLIMIT_10, - .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE, - .ReceiveAll = ETH_RECEIVEAll_DISABLE, - .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE, - .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL, - .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE, - .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL, - .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE, - .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter - .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT, - .HashTableHigh = 0x0, - .HashTableLow = 0x0, - .PauseTime = 0x0, - .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE, - .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4, - .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE, - .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE, - .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE, - .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT, - .VLANTagIdentifier = 0x0 - }; - - if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE) { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE; - } else { - macconf.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE; - } - - (void) HAL_ETH_ConfigMAC(heth, &macconf); -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h deleted file mode 100644 index c4fe5e7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32F7/stm32xx_emac_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32XX_EMAC_CONFIG_H__ -#define STM32XX_EMAC_CONFIG_H__ - -#define ETH_IP_VERSION_V1 - -#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c deleted file mode 100644 index 5255724..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_DISCO_H747I/stm32h7_eth_init.c +++ /dev/null @@ -1,149 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define ETHERNET 1 -#if (MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE == ETHERNET) -#if !defined(DISCO_H747I_ETHERNET_SOLDERBRIGE) -#error Hardware modifications are required for Ethernet on DISCO_H747I. see https://os.mbed.com/teams/ST/wiki/DISCO_H747I-modifications-for-Ethernet -#endif -#endif - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32h7xx_hal.h" - -#define ETH_TX_EN_Pin GPIO_PIN_11 -#define ETH_TX_EN_GPIO_Port GPIOG -#define ETH_TXD1_Pin GPIO_PIN_12 -#define ETH_TXD1_GPIO_Port GPIOG -#define ETH_TXD0_Pin GPIO_PIN_13 -#define ETH_TXD0_GPIO_Port GPIOG -#define ETH_MDC_SAI4_D1_Pin GPIO_PIN_1 -#define ETH_MDC_SAI4_D1_GPIO_Port GPIOC -#define ETH_MDIO_Pin GPIO_PIN_2 -#define ETH_MDIO_GPIO_Port GPIOA -#define ETH_REF_CLK_Pin GPIO_PIN_1 -#define ETH_REF_CLK_GPIO_Port GPIOA -#define ETH_CRS_DV_Pin GPIO_PIN_7 -#define ETH_CRS_DV_GPIO_Port GPIOA -#define ETH_RXD0_Pin GPIO_PIN_4 -#define ETH_RXD0_GPIO_Port GPIOC -#define ETH_RXD1_Pin GPIO_PIN_5 -#define ETH_RXD1_GPIO_Port GPIOC - - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStruct; - if (heth->Instance == ETH) { -#if defined(CORE_CM7) - /* Disable DCache for STM32H7 family */ - SCB_DisableDCache(); -#endif - - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOA_CLK_ENABLE(); - // __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - // __HAL_RCC_GPIOH_CLK_ENABLE(); - - /* Enable Peripheral clock */ - __HAL_RCC_ETH1MAC_CLK_ENABLE(); - __HAL_RCC_ETH1TX_CLK_ENABLE(); - __HAL_RCC_ETH1RX_CLK_ENABLE(); - - /**ETH GPIO Configuration - PG11 ------> ETH_TX_EN - PG12 ------> ETH_TXD1 - PG13 ------> ETH_TXD0 - PC1 ------> ETH_MDC - PA2 ------> ETH_MDIO - PA1 ------> ETH_REF_CLK - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - */ - GPIO_InitStruct.Pin = ETH_TX_EN_Pin | ETH_TXD1_Pin | ETH_TXD0_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = ETH_MDC_SAI4_D1_Pin | ETH_RXD0_Pin | ETH_RXD1_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = ETH_MDIO_Pin | ETH_REF_CLK_Pin | ETH_CRS_DV_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Peripheral clock disable */ - __HAL_RCC_ETH1MAC_CLK_DISABLE(); - __HAL_RCC_ETH1TX_CLK_DISABLE(); - __HAL_RCC_ETH1RX_CLK_DISABLE(); - - /**ETH GPIO Configuration - PG11 ------> ETH_TX_EN - PG12 ------> ETH_TXD1 - PG13 ------> ETH_TXD0 - PC1 ------> ETH_MDC - PA2 ------> ETH_MDIO - PA1 ------> ETH_REF_CLK - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - */ - HAL_GPIO_DeInit(GPIOG, ETH_TX_EN_Pin | ETH_TXD1_Pin | ETH_TXD0_Pin); - - HAL_GPIO_DeInit(GPIOC, ETH_MDC_SAI4_D1_Pin | ETH_RXD0_Pin | ETH_RXD1_Pin); - - HAL_GPIO_DeInit(GPIOA, ETH_MDIO_Pin | ETH_REF_CLK_Pin | ETH_CRS_DV_Pin); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c deleted file mode 100644 index 8c71ec7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI/stm32h7_eth_init.c +++ /dev/null @@ -1,160 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32h7xx_hal.h" - -#define MCO_Pin GPIO_PIN_0 -#define MCO_GPIO_Port GPIOH -#define RMII_MDC_Pin GPIO_PIN_1 -#define RMII_MDC_GPIO_Port GPIOC -#define RMII_REF_CLK_Pin GPIO_PIN_1 -#define RMII_REF_CLK_GPIO_Port GPIOA -#define RMII_MDIO_Pin GPIO_PIN_2 -#define RMII_MDIO_GPIO_Port GPIOA -#define RMII_CRS_DV_Pin GPIO_PIN_7 -#define RMII_CRS_DV_GPIO_Port GPIOA -#define RMII_RXD0_Pin GPIO_PIN_4 -#define RMII_RXD0_GPIO_Port GPIOC -#define RMII_RXD1_Pin GPIO_PIN_5 -#define RMII_RXD1_GPIO_Port GPIOC -#define RMII_TXD1_Pin GPIO_PIN_13 -#define RMII_TXD1_GPIO_Port GPIOB -#define TMS_Pin GPIO_PIN_13 -#define TMS_GPIO_Port GPIOA -#define TCK_Pin GPIO_PIN_14 -#define TCK_GPIO_Port GPIOA -#define RMII_TX_EN_Pin GPIO_PIN_11 -#define RMII_TX_EN_GPIO_Port GPIOG -#define RMII_TXD0_Pin GPIO_PIN_13 -#define RMII_TXD0_GPIO_Port GPIOG - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStruct; - if (heth->Instance == ETH) { - /* Disable DCache for STM32H7 family */ - SCB_DisableDCache(); - - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOH_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /* Enable Peripheral clock */ - __HAL_RCC_ETH1MAC_CLK_ENABLE(); - __HAL_RCC_ETH1TX_CLK_ENABLE(); - __HAL_RCC_ETH1RX_CLK_ENABLE(); - - /**ETH GPIO Configuration - PC1 ------> ETH_MDC - PA1 ------> ETH_REF_CLK - PA2 ------> ETH_MDIO - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - PB13 ------> ETH_TXD1 - PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 - */ - GPIO_InitStruct.Pin = RMII_MDC_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(RMII_MDC_GPIO_Port, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_RXD0_Pin | RMII_RXD1_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_TXD1_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_TX_EN_Pin | RMII_TXD0_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Disable Peripheral clock */ - __HAL_RCC_ETH1MAC_CLK_DISABLE(); - __HAL_RCC_ETH1TX_CLK_DISABLE(); - __HAL_RCC_ETH1RX_CLK_DISABLE(); - - /**ETH GPIO Configuration - PC1 ------> ETH_MDC - PA1 ------> ETH_REF_CLK - PA2 ------> ETH_MDIO - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - PB13 ------> ETH_TXD1 - PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 - */ - HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin); - - HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin); - - HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin); - - HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin | RMII_TXD0_Pin); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c deleted file mode 100644 index 8c71ec7..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/TARGET_NUCLEO_H743ZI2/stm32h7_eth_init.c +++ /dev/null @@ -1,160 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2018, STMicroelectronics - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef USE_USER_DEFINED_HAL_ETH_MSPINIT - -#include "stm32h7xx_hal.h" - -#define MCO_Pin GPIO_PIN_0 -#define MCO_GPIO_Port GPIOH -#define RMII_MDC_Pin GPIO_PIN_1 -#define RMII_MDC_GPIO_Port GPIOC -#define RMII_REF_CLK_Pin GPIO_PIN_1 -#define RMII_REF_CLK_GPIO_Port GPIOA -#define RMII_MDIO_Pin GPIO_PIN_2 -#define RMII_MDIO_GPIO_Port GPIOA -#define RMII_CRS_DV_Pin GPIO_PIN_7 -#define RMII_CRS_DV_GPIO_Port GPIOA -#define RMII_RXD0_Pin GPIO_PIN_4 -#define RMII_RXD0_GPIO_Port GPIOC -#define RMII_RXD1_Pin GPIO_PIN_5 -#define RMII_RXD1_GPIO_Port GPIOC -#define RMII_TXD1_Pin GPIO_PIN_13 -#define RMII_TXD1_GPIO_Port GPIOB -#define TMS_Pin GPIO_PIN_13 -#define TMS_GPIO_Port GPIOA -#define TCK_Pin GPIO_PIN_14 -#define TCK_GPIO_Port GPIOA -#define RMII_TX_EN_Pin GPIO_PIN_11 -#define RMII_TX_EN_GPIO_Port GPIOG -#define RMII_TXD0_Pin GPIO_PIN_13 -#define RMII_TXD0_GPIO_Port GPIOG - -/** - * Override HAL Eth Init function - */ -void HAL_ETH_MspInit(ETH_HandleTypeDef *heth) -{ - GPIO_InitTypeDef GPIO_InitStruct; - if (heth->Instance == ETH) { - /* Disable DCache for STM32H7 family */ - SCB_DisableDCache(); - - /* GPIO Ports Clock Enable */ - __HAL_RCC_GPIOH_CLK_ENABLE(); - __HAL_RCC_GPIOC_CLK_ENABLE(); - __HAL_RCC_GPIOA_CLK_ENABLE(); - __HAL_RCC_GPIOB_CLK_ENABLE(); - __HAL_RCC_GPIOG_CLK_ENABLE(); - - /* Enable Peripheral clock */ - __HAL_RCC_ETH1MAC_CLK_ENABLE(); - __HAL_RCC_ETH1TX_CLK_ENABLE(); - __HAL_RCC_ETH1RX_CLK_ENABLE(); - - /**ETH GPIO Configuration - PC1 ------> ETH_MDC - PA1 ------> ETH_REF_CLK - PA2 ------> ETH_MDIO - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - PB13 ------> ETH_TXD1 - PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 - */ - GPIO_InitStruct.Pin = RMII_MDC_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(RMII_MDC_GPIO_Port, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_RXD0_Pin | RMII_RXD1_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_TXD1_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(RMII_TXD1_GPIO_Port, &GPIO_InitStruct); - - GPIO_InitStruct.Pin = RMII_TX_EN_Pin | RMII_TXD0_Pin; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF11_ETH; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - } -} - -/** - * Override HAL Eth DeInit function - */ -void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth) -{ - if (heth->Instance == ETH) { - /* Disable Peripheral clock */ - __HAL_RCC_ETH1MAC_CLK_DISABLE(); - __HAL_RCC_ETH1TX_CLK_DISABLE(); - __HAL_RCC_ETH1RX_CLK_DISABLE(); - - /**ETH GPIO Configuration - PC1 ------> ETH_MDC - PA1 ------> ETH_REF_CLK - PA2 ------> ETH_MDIO - PA7 ------> ETH_CRS_DV - PC4 ------> ETH_RXD0 - PC5 ------> ETH_RXD1 - PB13 ------> ETH_TXD1 - PG11 ------> ETH_TX_EN - PG13 ------> ETH_TXD0 - */ - HAL_GPIO_DeInit(GPIOC, RMII_MDC_Pin | RMII_RXD0_Pin | RMII_RXD1_Pin); - - HAL_GPIO_DeInit(GPIOA, RMII_REF_CLK_Pin | RMII_MDIO_Pin | RMII_CRS_DV_Pin); - - HAL_GPIO_DeInit(RMII_TXD1_GPIO_Port, RMII_TXD1_Pin); - - HAL_GPIO_DeInit(GPIOG, RMII_TX_EN_Pin | RMII_TXD0_Pin); - } -} - -#endif /* USE_USER_DEFINED_HAL_ETH_MSPINIT */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c deleted file mode 100644 index 0fd341c..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.c +++ /dev/null @@ -1,590 +0,0 @@ -/** - ****************************************************************************** - * @file lan8742.c - * @author MCD Application Team - * @version V1.0.0 - * @date 08-March-2017 - * @brief This file provides a set of functions needed to manage the LAN742 - * PHY devices. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Includes ------------------------------------------------------------------*/ -#include "lan8742.h" - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @defgroup LAN8742 LAN8742 - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/** @defgroup LAN8742_Private_Defines LAN8742 Private Defines - * @{ - */ -#define LAN8742_SW_RESET_TO ((uint32_t)500U) -#define LAN8742_INIT_TO ((uint32_t)2000U) -#define LAN8742_MAX_DEV_ADDR ((uint32_t)31U) -/** - * @} - */ - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private function prototypes -----------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/** @defgroup LAN8742_Private_Functions LAN8742 Private Functions - * @{ - */ - -/** - * @brief Register IO functions to component object - * @param pObj: device object of LAN8742_Object_t. - * @param ioctx: holds device IO functions. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_ERROR if missing mandatory function - */ -int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx) -{ - if (!pObj || !ioctx->ReadReg || !ioctx->WriteReg || !ioctx->GetTick) { - return LAN8742_STATUS_ERROR; - } - - pObj->IO.Init = ioctx->Init; - pObj->IO.DeInit = ioctx->DeInit; - pObj->IO.ReadReg = ioctx->ReadReg; - pObj->IO.WriteReg = ioctx->WriteReg; - pObj->IO.GetTick = ioctx->GetTick; - - return LAN8742_STATUS_OK; -} - -/** - * @brief Initialize the lan8742 and configure the needed hardware resources - * @param pObj: device object LAN8742_Object_t. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_ADDRESS_ERROR if cannot find device address - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - * LAN8742_STATUS_RESET_TIMEOUT if cannot perform a software reset - */ -int32_t LAN8742_Init(lan8742_Object_t *pObj) -{ - uint32_t tickstart = 0, regvalue = 0, addr = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->Is_Initialized == 0) { - if (pObj->IO.Init != 0) { - /* GPIO and Clocks initialization */ - pObj->IO.Init(); - } - - /* for later check */ - pObj->DevAddr = LAN8742_MAX_DEV_ADDR + 1; - - /* Get the device address from special mode register */ - for (addr = 0; addr <= LAN8742_MAX_DEV_ADDR; addr ++) { - if (pObj->IO.ReadReg(addr, LAN8742_SMR, ®value) < 0) { - status = LAN8742_STATUS_READ_ERROR; - /* Can't read from this device address - continue with next address */ - continue; - } - - if ((regvalue & LAN8742_SMR_PHY_ADDR) == addr) { - pObj->DevAddr = addr; - status = LAN8742_STATUS_OK; - break; - } - } - - if (pObj->DevAddr > LAN8742_MAX_DEV_ADDR) { - status = LAN8742_STATUS_ADDRESS_ERROR; - } - - /* if device address is matched */ - if (status == LAN8742_STATUS_OK) { - /* set a software reset */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, LAN8742_BCR_SOFT_RESET) >= 0) { - /* get software reset status */ - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) >= 0) { - tickstart = pObj->IO.GetTick(); - - /* wait until software reset is done or timeout occured */ - while (regvalue & LAN8742_BCR_SOFT_RESET) { - if ((pObj->IO.GetTick() - tickstart) <= LAN8742_SW_RESET_TO) { - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, ®value) < 0) { - status = LAN8742_STATUS_READ_ERROR; - break; - } - } else { - status = LAN8742_STATUS_RESET_TIMEOUT; - } - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - } else { - status = LAN8742_STATUS_WRITE_ERROR; - } - } - } - - if (status == LAN8742_STATUS_OK) { - tickstart = pObj->IO.GetTick(); - - /* Wait for 2s to perform initialization */ - while ((pObj->IO.GetTick() - tickstart) <= LAN8742_INIT_TO) { - } - pObj->Is_Initialized = 1; - } - - return status; -} - -/** - * @brief De-Initialize the lan8742 and it's hardware resources - * @param pObj: device object LAN8742_Object_t. - * @retval None - */ -int32_t LAN8742_DeInit(lan8742_Object_t *pObj) -{ - if (pObj->Is_Initialized) { - if (pObj->IO.DeInit != 0) { - if (pObj->IO.DeInit() < 0) { - return LAN8742_STATUS_ERROR; - } - } - - pObj->Is_Initialized = 0; - } - - return LAN8742_STATUS_OK; -} - -/** - * @brief Disable the LAN8742 power down mode. - * @param pObj: device object LAN8742_Object_t. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { - readval &= ~LAN8742_BCR_POWER_DOWN; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Enable the LAN8742 power down mode. - * @param pObj: device object LAN8742_Object_t. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { - readval |= LAN8742_BCR_POWER_DOWN; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Start the auto negotiation process. - * @param pObj: device object LAN8742_Object_t. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { - readval |= LAN8742_BCR_AUTONEGO_EN; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Get the link state of LAN8742 device. - * @param pObj: Pointer to device object. - * @param pLinkState: Pointer to link state - * @retval LAN8742_STATUS_LINK_DOWN if link is down - * LAN8742_STATUS_AUTONEGO_NOTDONE if Auto nego not completed - * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD - * LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD - * LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD - * LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - - /* Read Status register */ - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { - return LAN8742_STATUS_READ_ERROR; - } - - /* Read Status register again */ - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BSR, &readval) < 0) { - return LAN8742_STATUS_READ_ERROR; - } - - if ((readval & LAN8742_BSR_LINK_STATUS) == 0) { - /* Return Link Down status */ - return LAN8742_STATUS_LINK_DOWN; - } - - /* Check Auto negotiaition */ - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) < 0) { - return LAN8742_STATUS_READ_ERROR; - } - - if ((readval & LAN8742_BCR_AUTONEGO_EN) != LAN8742_BCR_AUTONEGO_EN) { - if (((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) && ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE)) { - return LAN8742_STATUS_100MBITS_FULLDUPLEX; - } else if ((readval & LAN8742_BCR_SPEED_SELECT) == LAN8742_BCR_SPEED_SELECT) { - return LAN8742_STATUS_100MBITS_HALFDUPLEX; - } else if ((readval & LAN8742_BCR_DUPLEX_MODE) == LAN8742_BCR_DUPLEX_MODE) { - return LAN8742_STATUS_10MBITS_FULLDUPLEX; - } else { - return LAN8742_STATUS_10MBITS_HALFDUPLEX; - } - } else { /* Auto Nego enabled */ - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_PHYSCSR, &readval) < 0) { - return LAN8742_STATUS_READ_ERROR; - } - - /* Check if auto nego not done */ - if ((readval & LAN8742_PHYSCSR_AUTONEGO_DONE) == 0) { - return LAN8742_STATUS_AUTONEGO_NOTDONE; - } - - if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_FD) { - return LAN8742_STATUS_100MBITS_FULLDUPLEX; - } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_100BTX_HD) { - return LAN8742_STATUS_100MBITS_HALFDUPLEX; - } else if ((readval & LAN8742_PHYSCSR_HCDSPEEDMASK) == LAN8742_PHYSCSR_10BT_FD) { - return LAN8742_STATUS_10MBITS_FULLDUPLEX; - } else { - return LAN8742_STATUS_10MBITS_HALFDUPLEX; - } - } -} - -/** - * @brief Set the link state of LAN8742 device. - * @param pObj: Pointer to device object. - * @param pLinkState: link state can be one of the following - * LAN8742_STATUS_100MBITS_FULLDUPLEX if 100Mb/s FD - * LAN8742_STATUS_100MBITS_HALFDUPLEX if 100Mb/s HD - * LAN8742_STATUS_10MBITS_FULLDUPLEX if 10Mb/s FD - * LAN8742_STATUS_10MBITS_HALFDUPLEX if 10Mb/s HD - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_ERROR if parameter error - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState) -{ - uint32_t bcrvalue = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &bcrvalue) >= 0) { - /* Disable link config (Auto nego, speed and duplex) */ - bcrvalue &= ~(LAN8742_BCR_AUTONEGO_EN | LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE); - - if (LinkState == LAN8742_STATUS_100MBITS_FULLDUPLEX) { - bcrvalue |= (LAN8742_BCR_SPEED_SELECT | LAN8742_BCR_DUPLEX_MODE); - } else if (LinkState == LAN8742_STATUS_100MBITS_HALFDUPLEX) { - bcrvalue |= LAN8742_BCR_SPEED_SELECT; - } else if (LinkState == LAN8742_STATUS_10MBITS_FULLDUPLEX) { - bcrvalue |= LAN8742_BCR_DUPLEX_MODE; - } else { - /* Wrong link status parameter */ - status = LAN8742_STATUS_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - if (status == LAN8742_STATUS_OK) { - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, bcrvalue) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } - - return status; -} - -/** - * @brief Enable loopback mode. - * @param pObj: Pointer to device object. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { - readval |= LAN8742_BCR_LOOPBACK; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Disable loopback mode. - * @param pObj: Pointer to device object. - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_BCR, &readval) >= 0) { - readval &= ~LAN8742_BCR_LOOPBACK; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_BCR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Enable IT source. - * @param pObj: Pointer to device object. - * @param Interrupt: IT source to be enabled - * should be a value or a combination of the following: - * LAN8742_WOL_IT - * LAN8742_ENERGYON_IT - * LAN8742_AUTONEGO_COMPLETE_IT - * LAN8742_REMOTE_FAULT_IT - * LAN8742_LINK_DOWN_IT - * LAN8742_AUTONEGO_LP_ACK_IT - * LAN8742_PARALLEL_DETECTION_FAULT_IT - * LAN8742_AUTONEGO_PAGE_RECEIVED_IT - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0) { - readval |= Interrupt; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Disable IT source. - * @param pObj: Pointer to device object. - * @param Interrupt: IT source to be disabled - * should be a value or a combination of the following: - * LAN8742_WOL_IT - * LAN8742_ENERGYON_IT - * LAN8742_AUTONEGO_COMPLETE_IT - * LAN8742_REMOTE_FAULT_IT - * LAN8742_LINK_DOWN_IT - * LAN8742_AUTONEGO_LP_ACK_IT - * LAN8742_PARALLEL_DETECTION_FAULT_IT - * LAN8742_AUTONEGO_PAGE_RECEIVED_IT - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - * LAN8742_STATUS_WRITE_ERROR if connot write to register - */ -int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_IMR, &readval) >= 0) { - readval &= ~Interrupt; - - /* Apply configuration */ - if (pObj->IO.WriteReg(pObj->DevAddr, LAN8742_IMR, readval) < 0) { - status = LAN8742_STATUS_WRITE_ERROR; - } - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Clear IT flag. - * @param pObj: Pointer to device object. - * @param Interrupt: IT flag to be cleared - * should be a value or a combination of the following: - * LAN8742_WOL_IT - * LAN8742_ENERGYON_IT - * LAN8742_AUTONEGO_COMPLETE_IT - * LAN8742_REMOTE_FAULT_IT - * LAN8742_LINK_DOWN_IT - * LAN8742_AUTONEGO_LP_ACK_IT - * LAN8742_PARALLEL_DETECTION_FAULT_IT - * LAN8742_AUTONEGO_PAGE_RECEIVED_IT - * @retval LAN8742_STATUS_OK if OK - * LAN8742_STATUS_READ_ERROR if connot read register - */ -int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt) -{ - uint32_t readval = 0; - int32_t status = LAN8742_STATUS_OK; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) < 0) { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @brief Get IT Flag status. - * @param pObj: Pointer to device object. - * @param Interrupt: IT Flag to be checked, - * should be a value or a combination of the following: - * LAN8742_WOL_IT - * LAN8742_ENERGYON_IT - * LAN8742_AUTONEGO_COMPLETE_IT - * LAN8742_REMOTE_FAULT_IT - * LAN8742_LINK_DOWN_IT - * LAN8742_AUTONEGO_LP_ACK_IT - * LAN8742_PARALLEL_DETECTION_FAULT_IT - * LAN8742_AUTONEGO_PAGE_RECEIVED_IT - * @retval 1 IT flag is SET - * 0 IT flag is RESET - * LAN8742_STATUS_READ_ERROR if connot read register - */ -int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt) -{ - uint32_t readval = 0; - int32_t status = 0; - - if (pObj->IO.ReadReg(pObj->DevAddr, LAN8742_ISFR, &readval) >= 0) { - status = ((readval & Interrupt) == Interrupt); - } else { - status = LAN8742_STATUS_READ_ERROR; - } - - return status; -} - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h deleted file mode 100644 index 0214cff..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/lan8742/lan8742.h +++ /dev/null @@ -1,464 +0,0 @@ -/** - ****************************************************************************** - * @file lan8742.h - * @author MCD Application Team - * @version V1.0.0 - * @date 08-March-2017 - * @brief This file contains all the functions prototypes for the - * lan8742.c PHY driver. - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2017 STMicroelectronics

- * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __LAN8742_H -#define __LAN8742_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Includes ------------------------------------------------------------------*/ -#include - -/** @addtogroup BSP - * @{ - */ - -/** @addtogroup Component - * @{ - */ - -/** @defgroup LAN8742 - * @{ - */ -/* Exported constants --------------------------------------------------------*/ -/** @defgroup LAN8742_Exported_Constants LAN8742 Exported Constants - * @{ - */ - -/** @defgroup LAN8742_Registers_Mapping LAN8742 Registers Mapping - * @{ - */ -#define LAN8742_BCR ((uint16_t)0x0000U) -#define LAN8742_BSR ((uint16_t)0x0001U) -#define LAN8742_PHYI1R ((uint16_t)0x0002U) -#define LAN8742_PHYI2R ((uint16_t)0x0003U) -#define LAN8742_ANAR ((uint16_t)0x0004U) -#define LAN8742_ANLPAR ((uint16_t)0x0005U) -#define LAN8742_ANER ((uint16_t)0x0006U) -#define LAN8742_ANNPTR ((uint16_t)0x0007U) -#define LAN8742_ANNPRR ((uint16_t)0x0008U) -#define LAN8742_MMDACR ((uint16_t)0x000DU) -#define LAN8742_MMDAADR ((uint16_t)0x000EU) -#define LAN8742_ENCTR ((uint16_t)0x0010U) -#define LAN8742_MCSR ((uint16_t)0x0011U) -#define LAN8742_SMR ((uint16_t)0x0012U) -#define LAN8742_TPDCR ((uint16_t)0x0018U) -#define LAN8742_TCSR ((uint16_t)0x0019U) -#define LAN8742_SECR ((uint16_t)0x001AU) -#define LAN8742_SCSIR ((uint16_t)0x001BU) -#define LAN8742_CLR ((uint16_t)0x001CU) -#define LAN8742_ISFR ((uint16_t)0x001DU) -#define LAN8742_IMR ((uint16_t)0x001EU) -#define LAN8742_PHYSCSR ((uint16_t)0x001FU) -/** - * @} - */ - -/** @defgroup LAN8742_BCR_Bit_Definition LAN8742 BCR Bit Definition - * @{ - */ -#define LAN8742_BCR_SOFT_RESET ((uint16_t)0x8000U) -#define LAN8742_BCR_LOOPBACK ((uint16_t)0x4000U) -#define LAN8742_BCR_SPEED_SELECT ((uint16_t)0x2000U) -#define LAN8742_BCR_AUTONEGO_EN ((uint16_t)0x1000U) -#define LAN8742_BCR_POWER_DOWN ((uint16_t)0x0800U) -#define LAN8742_BCR_ISOLATE ((uint16_t)0x0400U) -#define LAN8742_BCR_RESTART_AUTONEGO ((uint16_t)0x0200U) -#define LAN8742_BCR_DUPLEX_MODE ((uint16_t)0x0100U) -/** - * @} - */ - -/** @defgroup LAN8742_BSR_Bit_Definition LAN8742 BSR Bit Definition - * @{ - */ -#define LAN8742_BSR_100BASE_T4 ((uint16_t)0x8000U) -#define LAN8742_BSR_100BASE_TX_FD ((uint16_t)0x4000U) -#define LAN8742_BSR_100BASE_TX_HD ((uint16_t)0x2000U) -#define LAN8742_BSR_10BASE_T_FD ((uint16_t)0x1000U) -#define LAN8742_BSR_10BASE_T_HD ((uint16_t)0x0800U) -#define LAN8742_BSR_100BASE_T2_FD ((uint16_t)0x0400U) -#define LAN8742_BSR_100BASE_T2_HD ((uint16_t)0x0200U) -#define LAN8742_BSR_EXTENDED_STATUS ((uint16_t)0x0100U) -#define LAN8742_BSR_AUTONEGO_CPLT ((uint16_t)0x0020U) -#define LAN8742_BSR_REMOTE_FAULT ((uint16_t)0x0010U) -#define LAN8742_BSR_AUTONEGO_ABILITY ((uint16_t)0x0008U) -#define LAN8742_BSR_LINK_STATUS ((uint16_t)0x0004U) -#define LAN8742_BSR_JABBER_DETECT ((uint16_t)0x0002U) -#define LAN8742_BSR_EXTENDED_CAP ((uint16_t)0x0001U) -/** - * @} - */ - -/** @defgroup LAN8742_PHYI1R_Bit_Definition LAN8742 PHYI1R Bit Definition - * @{ - */ -#define LAN8742_PHYI1R_OUI_3_18 ((uint16_t)0xFFFFU) -/** - * @} - */ - -/** @defgroup LAN8742_PHYI2R_Bit_Definition LAN8742 PHYI2R Bit Definition - * @{ - */ -#define LAN8742_PHYI2R_OUI_19_24 ((uint16_t)0xFC00U) -#define LAN8742_PHYI2R_MODEL_NBR ((uint16_t)0x03F0U) -#define LAN8742_PHYI2R_REVISION_NBR ((uint16_t)0x000FU) -/** - * @} - */ - -/** @defgroup LAN8742_ANAR_Bit_Definition LAN8742 ANAR Bit Definition - * @{ - */ -#define LAN8742_ANAR_NEXT_PAGE ((uint16_t)0x8000U) -#define LAN8742_ANAR_REMOTE_FAULT ((uint16_t)0x2000U) -#define LAN8742_ANAR_PAUSE_OPERATION ((uint16_t)0x0C00U) -#define LAN8742_ANAR_PO_NOPAUSE ((uint16_t)0x0000U) -#define LAN8742_ANAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) -#define LAN8742_ANAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) -#define LAN8742_ANAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) -#define LAN8742_ANAR_100BASE_TX_FD ((uint16_t)0x0100U) -#define LAN8742_ANAR_100BASE_TX ((uint16_t)0x0080U) -#define LAN8742_ANAR_10BASE_T_FD ((uint16_t)0x0040U) -#define LAN8742_ANAR_10BASE_T ((uint16_t)0x0020U) -#define LAN8742_ANAR_SELECTOR_FIELD ((uint16_t)0x000FU) -/** - * @} - */ - -/** @defgroup LAN8742_ANLPAR_Bit_Definition LAN8742 ANLPAR Bit Definition - * @{ - */ -#define LAN8742_ANLPAR_NEXT_PAGE ((uint16_t)0x8000U) -#define LAN8742_ANLPAR_REMOTE_FAULT ((uint16_t)0x2000U) -#define LAN8742_ANLPAR_PAUSE_OPERATION ((uint16_t)0x0C00U) -#define LAN8742_ANLPAR_PO_NOPAUSE ((uint16_t)0x0000U) -#define LAN8742_ANLPAR_PO_SYMMETRIC_PAUSE ((uint16_t)0x0400U) -#define LAN8742_ANLPAR_PO_ASYMMETRIC_PAUSE ((uint16_t)0x0800U) -#define LAN8742_ANLPAR_PO_ADVERTISE_SUPPORT ((uint16_t)0x0C00U) -#define LAN8742_ANLPAR_100BASE_TX_FD ((uint16_t)0x0100U) -#define LAN8742_ANLPAR_100BASE_TX ((uint16_t)0x0080U) -#define LAN8742_ANLPAR_10BASE_T_FD ((uint16_t)0x0040U) -#define LAN8742_ANLPAR_10BASE_T ((uint16_t)0x0020U) -#define LAN8742_ANLPAR_SELECTOR_FIELD ((uint16_t)0x000FU) -/** - * @} - */ - -/** @defgroup LAN8742_ANER_Bit_Definition LAN8742 ANER Bit Definition - * @{ - */ -#define LAN8742_ANER_RX_NP_LOCATION_ABLE ((uint16_t)0x0040U) -#define LAN8742_ANER_RX_NP_STORAGE_LOCATION ((uint16_t)0x0020U) -#define LAN8742_ANER_PARALLEL_DETECT_FAULT ((uint16_t)0x0010U) -#define LAN8742_ANER_LP_NP_ABLE ((uint16_t)0x0008U) -#define LAN8742_ANER_NP_ABLE ((uint16_t)0x0004U) -#define LAN8742_ANER_PAGE_RECEIVED ((uint16_t)0x0002U) -#define LAN8742_ANER_LP_AUTONEG_ABLE ((uint16_t)0x0001U) -/** - * @} - */ - -/** @defgroup LAN8742_ANNPTR_Bit_Definition LAN8742 ANNPTR Bit Definition - * @{ - */ -#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U) -#define LAN8742_ANNPTR_MESSAGE_PAGE ((uint16_t)0x2000U) -#define LAN8742_ANNPTR_ACK2 ((uint16_t)0x1000U) -#define LAN8742_ANNPTR_TOGGLE ((uint16_t)0x0800U) -#define LAN8742_ANNPTR_MESSAGGE_CODE ((uint16_t)0x07FFU) -/** - * @} - */ - -/** @defgroup LAN8742_ANNPRR_Bit_Definition LAN8742 ANNPRR Bit Definition - * @{ - */ -#define LAN8742_ANNPTR_NEXT_PAGE ((uint16_t)0x8000U) -#define LAN8742_ANNPRR_ACK ((uint16_t)0x4000U) -#define LAN8742_ANNPRR_MESSAGE_PAGE ((uint16_t)0x2000U) -#define LAN8742_ANNPRR_ACK2 ((uint16_t)0x1000U) -#define LAN8742_ANNPRR_TOGGLE ((uint16_t)0x0800U) -#define LAN8742_ANNPRR_MESSAGGE_CODE ((uint16_t)0x07FFU) -/** - * @} - */ - -/** @defgroup LAN8742_MMDACR_Bit_Definition LAN8742 MMDACR Bit Definition - * @{ - */ -#define LAN8742_MMDACR_MMD_FUNCTION ((uint16_t)0xC000U) -#define LAN8742_MMDACR_MMD_FUNCTION_ADDR ((uint16_t)0x0000U) -#define LAN8742_MMDACR_MMD_FUNCTION_DATA ((uint16_t)0x4000U) -#define LAN8742_MMDACR_MMD_DEV_ADDR ((uint16_t)0x001FU) -/** - * @} - */ - -/** @defgroup LAN8742_ENCTR_Bit_Definition LAN8742 ENCTR Bit Definition - * @{ - */ -#define LAN8742_ENCTR_TX_ENABLE ((uint16_t)0x8000U) -#define LAN8742_ENCTR_TX_TIMER ((uint16_t)0x6000U) -#define LAN8742_ENCTR_TX_TIMER_1S ((uint16_t)0x0000U) -#define LAN8742_ENCTR_TX_TIMER_768MS ((uint16_t)0x2000U) -#define LAN8742_ENCTR_TX_TIMER_512MS ((uint16_t)0x4000U) -#define LAN8742_ENCTR_TX_TIMER_265MS ((uint16_t)0x6000U) -#define LAN8742_ENCTR_RX_ENABLE ((uint16_t)0x1000U) -#define LAN8742_ENCTR_RX_MAX_INTERVAL ((uint16_t)0x0C00U) -#define LAN8742_ENCTR_RX_MAX_INTERVAL_64MS ((uint16_t)0x0000U) -#define LAN8742_ENCTR_RX_MAX_INTERVAL_256MS ((uint16_t)0x0400U) -#define LAN8742_ENCTR_RX_MAX_INTERVAL_512MS ((uint16_t)0x0800U) -#define LAN8742_ENCTR_RX_MAX_INTERVAL_1S ((uint16_t)0x0C00U) -#define LAN8742_ENCTR_EX_CROSS_OVER ((uint16_t)0x0002U) -#define LAN8742_ENCTR_EX_MANUAL_CROSS_OVER ((uint16_t)0x0001U) -/** - * @} - */ - -/** @defgroup LAN8742_MCSR_Bit_Definition LAN8742 MCSR Bit Definition - * @{ - */ -#define LAN8742_MCSR_EDPWRDOWN ((uint16_t)0x2000U) -#define LAN8742_MCSR_FARLOOPBACK ((uint16_t)0x0200U) -#define LAN8742_MCSR_ALTINT ((uint16_t)0x0040U) -#define LAN8742_MCSR_ENERGYON ((uint16_t)0x0002U) -/** - * @} - */ - -/** @defgroup LAN8742_SMR_Bit_Definition LAN8742 SMR Bit Definition - * @{ - */ -#define LAN8742_SMR_MODE ((uint16_t)0x00E0U) -#define LAN8742_SMR_PHY_ADDR ((uint16_t)0x001FU) -/** - * @} - */ - -/** @defgroup LAN8742_TPDCR_Bit_Definition LAN8742 TPDCR Bit Definition - * @{ - */ -#define LAN8742_TPDCR_DELAY_IN ((uint16_t)0x8000U) -#define LAN8742_TPDCR_LINE_BREAK_COUNTER ((uint16_t)0x7000U) -#define LAN8742_TPDCR_PATTERN_HIGH ((uint16_t)0x0FC0U) -#define LAN8742_TPDCR_PATTERN_LOW ((uint16_t)0x003FU) -/** - * @} - */ - -/** @defgroup LAN8742_TCSR_Bit_Definition LAN8742 TCSR Bit Definition - * @{ - */ -#define LAN8742_TCSR_TDR_ENABLE ((uint16_t)0x8000U) -#define LAN8742_TCSR_TDR_AD_FILTER_ENABLE ((uint16_t)0x4000U) -#define LAN8742_TCSR_TDR_CH_CABLE_TYPE ((uint16_t)0x0600U) -#define LAN8742_TCSR_TDR_CH_CABLE_DEFAULT ((uint16_t)0x0000U) -#define LAN8742_TCSR_TDR_CH_CABLE_SHORTED ((uint16_t)0x0200U) -#define LAN8742_TCSR_TDR_CH_CABLE_OPEN ((uint16_t)0x0400U) -#define LAN8742_TCSR_TDR_CH_CABLE_MATCH ((uint16_t)0x0600U) -#define LAN8742_TCSR_TDR_CH_STATUS ((uint16_t)0x0100U) -#define LAN8742_TCSR_TDR_CH_LENGTH ((uint16_t)0x00FFU) -/** - * @} - */ - -/** @defgroup LAN8742_SCSIR_Bit_Definition LAN8742 SCSIR Bit Definition - * @{ - */ -#define LAN8742_SCSIR_AUTO_MDIX_ENABLE ((uint16_t)0x8000U) -#define LAN8742_SCSIR_CHANNEL_SELECT ((uint16_t)0x2000U) -#define LAN8742_SCSIR_SQE_DISABLE ((uint16_t)0x0800U) -#define LAN8742_SCSIR_XPOLALITY ((uint16_t)0x0010U) -/** - * @} - */ - -/** @defgroup LAN8742_CLR_Bit_Definition LAN8742 CLR Bit Definition - * @{ - */ -#define LAN8742_CLR_CABLE_LENGTH ((uint16_t)0xF000U) -/** - * @} - */ - -/** @defgroup LAN8742_IMR_ISFR_Bit_Definition LAN8742 IMR ISFR Bit Definition - * @{ - */ -#define LAN8742_INT_8 ((uint16_t)0x0100U) -#define LAN8742_INT_7 ((uint16_t)0x0080U) -#define LAN8742_INT_6 ((uint16_t)0x0040U) -#define LAN8742_INT_5 ((uint16_t)0x0020U) -#define LAN8742_INT_4 ((uint16_t)0x0010U) -#define LAN8742_INT_3 ((uint16_t)0x0008U) -#define LAN8742_INT_2 ((uint16_t)0x0004U) -#define LAN8742_INT_1 ((uint16_t)0x0002U) -/** - * @} - */ - -/** @defgroup LAN8742_PHYSCSR_Bit_Definition LAN8742 PHYSCSR Bit Definition - * @{ - */ -#define LAN8742_PHYSCSR_AUTONEGO_DONE ((uint16_t)0x1000U) -#define LAN8742_PHYSCSR_HCDSPEEDMASK ((uint16_t)0x001CU) -#define LAN8742_PHYSCSR_10BT_HD ((uint16_t)0x0004U) -#define LAN8742_PHYSCSR_10BT_FD ((uint16_t)0x0014U) -#define LAN8742_PHYSCSR_100BTX_HD ((uint16_t)0x0008U) -#define LAN8742_PHYSCSR_100BTX_FD ((uint16_t)0x0018U) -/** - * @} - */ - -/** @defgroup LAN8742_Status LAN8742 Status - * @{ - */ - -#define LAN8742_STATUS_READ_ERROR ((int32_t)-5) -#define LAN8742_STATUS_WRITE_ERROR ((int32_t)-4) -#define LAN8742_STATUS_ADDRESS_ERROR ((int32_t)-3) -#define LAN8742_STATUS_RESET_TIMEOUT ((int32_t)-2) -#define LAN8742_STATUS_ERROR ((int32_t)-1) -#define LAN8742_STATUS_OK ((int32_t) 0) -#define LAN8742_STATUS_LINK_DOWN ((int32_t) 1) -#define LAN8742_STATUS_100MBITS_FULLDUPLEX ((int32_t) 2) -#define LAN8742_STATUS_100MBITS_HALFDUPLEX ((int32_t) 3) -#define LAN8742_STATUS_10MBITS_FULLDUPLEX ((int32_t) 4) -#define LAN8742_STATUS_10MBITS_HALFDUPLEX ((int32_t) 5) -#define LAN8742_STATUS_AUTONEGO_NOTDONE ((int32_t) 6) -/** - * @} - */ - -/** @defgroup LAN8742_IT_Flags LAN8742 IT Flags - * @{ - */ -#define LAN8742_WOL_IT LAN8742_INT_8 -#define LAN8742_ENERGYON_IT LAN8742_INT_7 -#define LAN8742_AUTONEGO_COMPLETE_IT LAN8742_INT_6 -#define LAN8742_REMOTE_FAULT_IT LAN8742_INT_5 -#define LAN8742_LINK_DOWN_IT LAN8742_INT_4 -#define LAN8742_AUTONEGO_LP_ACK_IT LAN8742_INT_3 -#define LAN8742_PARALLEL_DETECTION_FAULT_IT LAN8742_INT_2 -#define LAN8742_AUTONEGO_PAGE_RECEIVED_IT LAN8742_INT_1 -/** - * @} - */ - -/** - * @} - */ - -/* Exported types ------------------------------------------------------------*/ -/** @defgroup LAN8742_Exported_Types LAN8742 Exported Types - * @{ - */ -typedef int32_t (*lan8742_Init_Func)(void); -typedef int32_t (*lan8742_DeInit_Func)(void); -typedef int32_t (*lan8742_ReadReg_Func)(uint32_t, uint32_t, uint32_t *); -typedef int32_t (*lan8742_WriteReg_Func)(uint32_t, uint32_t, uint32_t); -typedef int32_t (*lan8742_GetTick_Func)(void); - -typedef struct { - lan8742_Init_Func Init; - lan8742_DeInit_Func DeInit; - lan8742_WriteReg_Func WriteReg; - lan8742_ReadReg_Func ReadReg; - lan8742_GetTick_Func GetTick; -} lan8742_IOCtx_t; - - -typedef struct { - uint32_t DevAddr; - uint32_t Is_Initialized; - lan8742_IOCtx_t IO; - void *pData; -} lan8742_Object_t; -/** - * @} - */ - -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions --------------------------------------------------------*/ -/** @defgroup LAN8742_Exported_Functions LAN8742 Exported Functions - * @{ - */ -int32_t LAN8742_RegisterBusIO(lan8742_Object_t *pObj, lan8742_IOCtx_t *ioctx); -int32_t LAN8742_Init(lan8742_Object_t *pObj); -int32_t LAN8742_DeInit(lan8742_Object_t *pObj); -int32_t LAN8742_DisablePowerDownMode(lan8742_Object_t *pObj); -int32_t LAN8742_EnablePowerDownMode(lan8742_Object_t *pObj); -int32_t LAN8742_StartAutoNego(lan8742_Object_t *pObj); -int32_t LAN8742_GetLinkState(lan8742_Object_t *pObj); -int32_t LAN8742_SetLinkState(lan8742_Object_t *pObj, uint32_t LinkState); -int32_t LAN8742_EnableLoopbackMode(lan8742_Object_t *pObj); -int32_t LAN8742_DisableLoopbackMode(lan8742_Object_t *pObj); -int32_t LAN8742_EnableIT(lan8742_Object_t *pObj, uint32_t Interrupt); -int32_t LAN8742_DisableIT(lan8742_Object_t *pObj, uint32_t Interrupt); -int32_t LAN8742_ClearIT(lan8742_Object_t *pObj, uint32_t Interrupt); -int32_t LAN8742_GetITStatus(lan8742_Object_t *pObj, uint32_t Interrupt); -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* __LAN8742_H */ - - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ - -/** - * @} - */ -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h b/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h deleted file mode 100644 index cd943cc..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/TARGET_STM32H7/stm32xx_emac_config.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32XX_EMAC_CONFIG_H__ -#define STM32XX_EMAC_CONFIG_H__ - -#define ETH_IP_VERSION_V2 - -#endif // #define STM32XX_EMAC_CONFIG_H__ diff --git a/features/netsocket/emac-drivers/TARGET_STM/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_STM/mbed_lib.json deleted file mode 100644 index 5a86535..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/mbed_lib.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "stm32-emac", - "config": { - "eth-rxbufnb": 4, - "eth-txbufnb": 4, - "thread-stacksize": { - "help": "Stack size for stm32_emac_thread", - "value": 1024 - }, - "eth-phy-address": { - "help" : "Configures actual PHY address according to pullup/down status of PHYAD pin(s)", - "value" : 0 - }, - "eth-phy-media-interface": { - "help" : "Selects Connection to PHY Chip: ETH_MEDIA_INTERFACE_RMII / ETH_MEDIA_INTERFACE_MII", - "value" : "ETH_MEDIA_INTERFACE_RMII" - }, - "eth-phy-AutoNegotiation": { - "help" : "Selects AutoNegotiation mode : ETH_AUTONEGOTIATION_ENABLE / ETH_AUTONEGOTIATION_DISABLE", - "value" : "ETH_AUTONEGOTIATION_ENABLE" - }, - "eth-phy-DuplexMode": { - "help" : "Selects DuplexMode mode : ETH_MODE_FULLDUPLEX / ETH_MODE_HALFDUPLEX", - "value" : "ETH_MODE_FULLDUPLEX" - }, - "eth-phy-Speed": { - "help" : "Selects Speed mode : ETH_SPEED_100M / ETH_SPEED_10M", - "value" : "ETH_SPEED_100M" - }, - "eth-phy-reset-delay": { - "help" : "Reset process time - Default value: 0.5s as specified in LAN8742A datasheet", - "value" : "500" - }, - "eth-phy-status-register": { - "help" : "PHY register Offset with auto-negotiation result - Default value is LAN8742A PHY Special Control/Status Register", - "value" : "31" - }, - "eth-phy-speed-status": { - "help" : "Speed mask information in eth-phy-status-register", - "value" : "0x0004" - }, - "eth-phy-duplex-status": { - "help" : "Duplex mask information in eth-phy-status-register", - "value" : "0x0010" - } - }, - "target_overrides": { - "NUCLEO_F207ZG": { - "eth-rxbufnb": 2, - "eth-txbufnb": 4 - }, - "STM32H7": { - "eth-txbufnb": 10 - }, - "ARCH_MAX": { - "eth-phy-address": 1 - } - } -} diff --git a/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.cpp b/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.cpp deleted file mode 100644 index 7ae8276..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.cpp +++ /dev/null @@ -1,1086 +0,0 @@ -/* Copyright (c) 2017-2019 ARM Limited - * Copyright (c) 2017-2019 STMicroelectronics - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if DEVICE_EMAC - -#include - -#include "cmsis_os.h" - -#include "mbed.h" -#include "mbed_interface.h" -#include "mbed_assert.h" -#include "mbed_shared_queues.h" -#include "netsocket/nsapi_types.h" - -#include "stm32xx_emac_config.h" -#include "stm32xx_emac.h" - -#include "mbed-trace/mbed_trace.h" - -#if defined(ETH_IP_VERSION_V2) -#define TRACE_GROUP "STE2" -#else -#define TRACE_GROUP "STE1" -#endif - -/* mbed trace feature is supported */ -/* ex in mbed_app.json */ -/* "mbed-trace.enable": "1" */ - -/* mbed_trace: debug traces (tr_debug) can be disabled here with no change in mbed_app.json */ -// #undef TRACE_LEVEL_DEBUG -// #define TRACE_LEVEL_DEBUG 0 - -#if defined(ETH_IP_VERSION_V2) -#include "lan8742/lan8742.h" -#include "lwip/memp.h" -#include "lwip/api.h" -#endif - -using namespace std::chrono; - -/* \brief Flags for worker thread */ -#define FLAG_RX 1 - -/** \brief Driver thread priority */ -#define THREAD_PRIORITY (osPriorityHigh) - -#define PHY_TASK_PERIOD 200ms - -#define STM_HWADDR_SIZE (6) -#define STM_ETH_MTU_SIZE 1500 -#define STM_ETH_IF_NAME "st" - -#ifndef ETH_IP_VERSION_V2 - -#if defined (__ICCARM__) /*!< IAR Compiler */ -#pragma data_alignment=4 -#endif -__ALIGN_BEGIN ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB] __ALIGN_END; /* Ethernet Rx DMA Descriptor */ - -#if defined (__ICCARM__) /*!< IAR Compiler */ -#pragma data_alignment=4 -#endif -__ALIGN_BEGIN ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB] __ALIGN_END; /* Ethernet Tx DMA Descriptor */ - -#if defined (__ICCARM__) /*!< IAR Compiler */ -#pragma data_alignment=4 -#endif -__ALIGN_BEGIN uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE] __ALIGN_END; /* Ethernet Receive Buffer */ - -#if defined (__ICCARM__) /*!< IAR Compiler */ -#pragma data_alignment=4 -#endif -__ALIGN_BEGIN uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE] __ALIGN_END; /* Ethernet Transmit Buffer */ - -#else // ETH_IP_VERSION_V2 - -#if defined ( __ICCARM__ ) /*!< IAR Compiler */ - -#pragma location=0x30040000 -ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */ -#pragma location=0x30040100 -ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */ -#pragma location=0x30040400 -uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE]; /* Ethernet Receive Buffers */ - -#elif defined ( __GNUC__ ) /* GCC & ARMC6*/ - -ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */ -ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection"))); /* Ethernet Tx DMA Descriptors */ -uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_MAX_PACKET_SIZE] __attribute__((section(".RxArraySection"))); /* Ethernet Receive Buffers */ - -#endif - -static lan8742_Object_t LAN8742; - -static int32_t ETH_PHY_IO_Init(void); -static int32_t ETH_PHY_IO_DeInit(void); -static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal); -static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal); -static int32_t ETH_PHY_IO_GetTick(void); - -static lan8742_IOCtx_t LAN8742_IOCtx = { - ETH_PHY_IO_Init, - ETH_PHY_IO_DeInit, - ETH_PHY_IO_WriteReg, - ETH_PHY_IO_ReadReg, - ETH_PHY_IO_GetTick -}; - -static ETH_TxPacketConfig TxConfig; - -#endif // ETH_IP_VERSION_V2 - -__weak uint8_t mbed_otp_mac_address(char *mac); -void mbed_default_mac_address(char *mac); - -#ifdef __cplusplus -extern "C" { -#endif - -void _eth_config_mac(ETH_HandleTypeDef *heth); -void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth); -void ETH_IRQHandler(void); - -#ifdef __cplusplus -} -#endif - -#ifdef ETH_IP_VERSION_V2 -bool _phy_init() -{ - /* Set PHY IO functions */ - LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx); - - /* Initialize the LAN8742 ETH PHY */ - return LAN8742_Init(&LAN8742) == LAN8742_STATUS_OK; -} - -int32_t _phy_get_state() -{ - return LAN8742_GetLinkState(&LAN8742); -} - -bool _phy_get_duplex_and_speed(int32_t phy_state, uint32_t *duplex, uint32_t *speed) -{ - switch (phy_state) { - case LAN8742_STATUS_100MBITS_FULLDUPLEX: - *duplex = ETH_FULLDUPLEX_MODE; - *speed = ETH_SPEED_100M; - break; - case LAN8742_STATUS_100MBITS_HALFDUPLEX: - *duplex = ETH_HALFDUPLEX_MODE; - *speed = ETH_SPEED_100M; - break; - case LAN8742_STATUS_10MBITS_FULLDUPLEX: - *duplex = ETH_FULLDUPLEX_MODE; - *speed = ETH_SPEED_10M; - break; - case LAN8742_STATUS_10MBITS_HALFDUPLEX: - *duplex = ETH_HALFDUPLEX_MODE; - *speed = ETH_SPEED_10M; - break; - default: - return false; - } - - return true; -} - -bool _phy_is_up(int32_t phy_state) -{ - return phy_state > LAN8742_STATUS_LINK_DOWN; -} - -static void MPU_Config(void) -{ - MPU_Region_InitTypeDef MPU_InitStruct; - - /* Disable the MPU */ - HAL_MPU_Disable(); - - /* Configure the MPU attributes as Device not cacheable - for ETH DMA descriptors */ - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.BaseAddress = 0x30040000; - MPU_InitStruct.Size = MPU_REGION_SIZE_1KB; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER0; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.SubRegionDisable = 0x00; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - /* Configure the MPU attributes as Cacheable write through - for LwIP RAM heap which contains the Tx buffers */ - MPU_InitStruct.Enable = MPU_REGION_ENABLE; - MPU_InitStruct.BaseAddress = 0x30044000; - MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; - MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; - MPU_InitStruct.Number = MPU_REGION_NUMBER1; - MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; - MPU_InitStruct.SubRegionDisable = 0x00; - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; - - HAL_MPU_ConfigRegion(&MPU_InitStruct); - - /* Enable the MPU */ - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); -} - -#endif - - - -/** - * Ethernet Rx Transfer completed callback - * - * @param heth: ETH handle - * @retval None - */ -void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth) -{ - STM32_EMAC &emac = STM32_EMAC::get_instance(); - if (emac.thread) { - osThreadFlagsSet(emac.thread, FLAG_RX); - } -} - -/** - * Ethernet IRQ Handler - * - * @param None - * @retval None - */ -void ETH_IRQHandler(void) -{ - STM32_EMAC &emac = STM32_EMAC::get_instance(); - HAL_ETH_IRQHandler(&emac.EthHandle); -} - -STM32_EMAC::STM32_EMAC() - : thread(0) -#ifdef ETH_IP_VERSION_V2 - , phy_status(0) -#endif -{ -} - -static osThreadId_t create_new_thread(const char *threadName, void (*thread)(void *arg), void *arg, int stacksize, osPriority_t priority, mbed_rtos_storage_thread_t *thread_cb) -{ - osThreadAttr_t attr = {0}; - attr.name = threadName; - attr.stack_mem = malloc(stacksize); - attr.cb_mem = thread_cb; - attr.stack_size = stacksize; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = priority; - return osThreadNew(thread, arg, &attr); -} - -/** - * In this function, the hardware should be initialized. - */ -bool STM32_EMAC::low_level_init_successful() -#ifndef ETH_IP_VERSION_V2 -{ - uint32_t PHY_ID; - - /* Init ETH */ - uint8_t MACAddr[6]; - EthHandle.Instance = ETH; - EthHandle.Init.AutoNegotiation = MBED_CONF_STM32_EMAC_ETH_PHY_AUTONEGOTIATION; - EthHandle.Init.Speed = MBED_CONF_STM32_EMAC_ETH_PHY_SPEED; - EthHandle.Init.DuplexMode = MBED_CONF_STM32_EMAC_ETH_PHY_DUPLEXMODE; - EthHandle.Init.PhyAddress = MBED_CONF_STM32_EMAC_ETH_PHY_ADDRESS; -#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) - MACAddr[0] = MBED_MAC_ADDR_0; - MACAddr[1] = MBED_MAC_ADDR_1; - MACAddr[2] = MBED_MAC_ADDR_2; - MACAddr[3] = MBED_MAC_ADDR_3; - MACAddr[4] = MBED_MAC_ADDR_4; - MACAddr[5] = MBED_MAC_ADDR_5; -#else - mbed_mac_address((char *)MACAddr); -#endif - EthHandle.Init.MACAddr = &MACAddr[0]; - EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; - EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE; - EthHandle.Init.MediaInterface = MBED_CONF_STM32_EMAC_ETH_PHY_MEDIA_INTERFACE; - tr_info("PHY Addr %u AutoNegotiation %u", EthHandle.Init.PhyAddress, EthHandle.Init.AutoNegotiation); - tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]); - tr_info("ETH buffers : %u Rx %u Tx", ETH_RXBUFNB, ETH_TXBUFNB); - - if (HAL_ETH_Init(&EthHandle) != HAL_OK) { - tr_error("HAL_ETH_Init issue"); - /* HAL_ETH_Init returns TIMEOUT when Ethernet cable is not plugged */; - } - - uint32_t TempRegisterValue; - if (HAL_ETH_ReadPHYRegister(&EthHandle, 2, &TempRegisterValue) != HAL_OK) { - tr_error("HAL_ETH_ReadPHYRegister 2 issue"); - } - PHY_ID = (TempRegisterValue << 16); - if (HAL_ETH_ReadPHYRegister(&EthHandle, 3, &TempRegisterValue) != HAL_OK) { - tr_error("HAL_ETH_ReadPHYRegister 3 issue"); - } - PHY_ID |= (TempRegisterValue & 0XFFF0); - tr_info("PHY ID %#X", PHY_ID); - - /* Initialize Tx Descriptors list: Chain Mode */ - if (HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB) != HAL_OK) { - tr_error("HAL_ETH_DMATxDescListInit issue"); - return false; - } - - /* Initialize Rx Descriptors list: Chain Mode */ - if (HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB) != HAL_OK) { - tr_error("HAL_ETH_DMARxDescListInit issue"); - return false; - } - - /* Configure MAC */ - _eth_config_mac(&EthHandle); - - /* Enable MAC and DMA transmission and reception */ - if (HAL_ETH_Start(&EthHandle) != HAL_OK) { - tr_error("HAL_ETH_Start issue"); - return false; - } - - tr_info("low_level_init_successful"); - return true; -} -#else // ETH_IP_VERSION_V2 -{ - uint32_t idx; - - MPU_Config(); - - /* Init ETH */ - uint8_t MACAddr[6]; - EthHandle.Instance = ETH; -#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) - MACAddr[0] = MBED_MAC_ADDR_0; - MACAddr[1] = MBED_MAC_ADDR_1; - MACAddr[2] = MBED_MAC_ADDR_2; - MACAddr[3] = MBED_MAC_ADDR_3; - MACAddr[4] = MBED_MAC_ADDR_4; - MACAddr[5] = MBED_MAC_ADDR_5; -#else - mbed_mac_address((char *)MACAddr); -#endif - EthHandle.Init.MACAddr = &MACAddr[0]; - EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE; - EthHandle.Init.RxDesc = DMARxDscrTab; - EthHandle.Init.TxDesc = DMATxDscrTab; - EthHandle.Init.RxBuffLen = 1524; - - tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]); - tr_info("ETH buffers : %u Rx %u Tx", ETH_RX_DESC_CNT, ETH_TX_DESC_CNT); - - if (HAL_ETH_Init(&EthHandle) != HAL_OK) { - return false; - } - - memset(&TxConfig, 0, sizeof(ETH_TxPacketConfig)); - TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD; - TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC; - TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT; - - for (idx = 0; idx < ETH_RX_DESC_CNT; idx++) { - HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL); - } - - tr_info("low_level_init_successful"); - return _phy_init(); -} -#endif // ETH_IP_VERSION_V2 - -/** - * This function should do the actual transmission of the packet. The packet is - * contained in the memory buffer chain that is passed to the function. - * - * @param buf the MAC packet to send (e.g. IP packet including MAC addresses and type) - * @return true if the packet could be sent - * false value if the packet couldn't be sent - * - * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to - * strange results. You might consider waiting for space in the DMA queue - * to become availale since the stack doesn't retry to send a packet - * dropped because of memory failure (except for the TCP timers). - */ -bool STM32_EMAC::link_out(emac_mem_buf_t *buf) -#ifndef ETH_IP_VERSION_V2 -{ - bool success = true; - emac_mem_buf_t *q; - uint8_t *buffer = reinterpret_cast(EthHandle.TxDesc->Buffer1Addr); - __IO ETH_DMADescTypeDef *DmaTxDesc; - uint32_t framelength = 0; - uint32_t bufferoffset = 0; - uint32_t byteslefttocopy = 0; - uint32_t payloadoffset = 0; - DmaTxDesc = EthHandle.TxDesc; - - /* Get exclusive access */ - TXLockMutex.lock(); - - /* copy frame from pbufs to driver buffers */ - for (q = buf; q != NULL; q = memory_manager->get_next(q)) { - /* Is this buffer available? If not, goto error */ - if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { - success = false; - goto error; - } - - /* Get bytes in current lwIP buffer */ - byteslefttocopy = memory_manager->get_len(q); - payloadoffset = 0; - - /* Check if the length of data to copy is bigger than Tx buffer size*/ - while ((byteslefttocopy + bufferoffset) > ETH_TX_BUF_SIZE) { - /* Copy data to Tx buffer*/ - memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, (ETH_TX_BUF_SIZE - bufferoffset)); - - /* Point to next descriptor */ - DmaTxDesc = reinterpret_cast(DmaTxDesc->Buffer2NextDescAddr); - - /* Check if the buffer is available */ - if ((DmaTxDesc->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET) { - success = false; - goto error; - } - - buffer = reinterpret_cast(DmaTxDesc->Buffer1Addr); - - byteslefttocopy = byteslefttocopy - (ETH_TX_BUF_SIZE - bufferoffset); - payloadoffset = payloadoffset + (ETH_TX_BUF_SIZE - bufferoffset); - framelength = framelength + (ETH_TX_BUF_SIZE - bufferoffset); - bufferoffset = 0; - } - - /* Copy the remaining bytes */ - memcpy(static_cast(buffer) + bufferoffset, static_cast(memory_manager->get_ptr(q)) + payloadoffset, byteslefttocopy); - bufferoffset = bufferoffset + byteslefttocopy; - framelength = framelength + byteslefttocopy; - } - - /* Prepare transmit descriptors to give to DMA */ - if (HAL_ETH_TransmitFrame(&EthHandle, framelength) != HAL_OK) { - tr_error("HAL_ETH_TransmitFrame issue"); - success = false; - } - -error: - - /* When Transmit Underflow flag is set, clear it and issue a Transmit Poll Demand to resume transmission */ - if ((EthHandle.Instance->DMASR & ETH_DMASR_TUS) != (uint32_t)RESET) { - /* Clear TUS ETHERNET DMA flag */ - EthHandle.Instance->DMASR = ETH_DMASR_TUS; - - /* Resume DMA transmission*/ - EthHandle.Instance->DMATPDR = 0; - } - - memory_manager->free(buf); - - /* Restore access */ - TXLockMutex.unlock(); - - return success; -} -#else // ETH_IP_VERSION_V2 -{ - bool success = false; - uint32_t i = 0; - uint32_t frameLength = 0; - struct pbuf *q; - ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT]; - HAL_StatusTypeDef status; - struct pbuf *p = NULL; - p = (struct pbuf *)buf; - /* Get exclusive access */ - TXLockMutex.lock(); - - memset(Txbuffer, 0, ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef)); - - /* copy frame from pbufs to driver buffers */ - for (q = p; q != NULL; q = q->next) { - if (i >= ETH_TX_DESC_CNT) { - tr_error("Error : ETH_TX_DESC_CNT not sufficient"); - goto error; - } - - Txbuffer[i].buffer = (uint8_t *)q->payload; - Txbuffer[i].len = q->len; - frameLength += q->len; - - if (i > 0) { - Txbuffer[i - 1].next = &Txbuffer[i]; - } - - if (q->next == NULL) { - Txbuffer[i].next = NULL; - } - - i++; - } - - TxConfig.Length = frameLength; - TxConfig.TxBuffer = Txbuffer; - - status = HAL_ETH_Transmit(&EthHandle, &TxConfig, 50); - if (status == HAL_OK) { - success = 1; - } else { - tr_error("Error returned by HAL_ETH_Transmit (%d)", status); - success = 0; - } - -error: - - if (p->ref > 1) { - pbuf_free(p); - } - - /* Restore access */ - TXLockMutex.unlock(); - - return success; -} -#endif // ETH_IP_VERSION_V2 - -/** - * Should allocate a contiguous memory buffer and transfer the bytes of the incoming - * packet to the buffer. - * - * @param buf If a frame was received and the memory buffer allocation was successful, a memory - * buffer filled with the received packet (including MAC header) - * @return negative value when no more frames, - * zero when frame is received - */ -int STM32_EMAC::low_level_input(emac_mem_buf_t **buf) -#ifndef ETH_IP_VERSION_V2 -{ - uint32_t len = 0; - uint8_t *buffer; - __IO ETH_DMADescTypeDef *dmarxdesc; - uint32_t bufferoffset = 0; - uint32_t byteslefttocopy = 0; - emac_mem_buf_t *q; - uint32_t payloadoffset = 0; - - /* get received frame */ - if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) { - tr_debug("low_level_input no frame"); - return -1; - } - - /* Obtain the size of the packet and put it into the "len" variable. */ - len = EthHandle.RxFrameInfos.length; - buffer = reinterpret_cast(EthHandle.RxFrameInfos.buffer); - byteslefttocopy = len; - - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - - if (len > 0 && len <= ETH_RX_BUF_SIZE) { - tr_debug("low_level_input len %u", len); - /* Allocate a memory buffer chain from buffer pool */ - *buf = memory_manager->alloc_pool(len, 0); - } - - if (*buf != NULL) { - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - bufferoffset = 0; - for (q = *buf; q != NULL; q = memory_manager->get_next(q)) { - byteslefttocopy = memory_manager->get_len(q); - payloadoffset = 0; - - /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/ - while ((byteslefttocopy + bufferoffset) > ETH_RX_BUF_SIZE) { - /* Copy data to pbuf */ - memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, ETH_RX_BUF_SIZE - bufferoffset); - - /* Point to next descriptor */ - dmarxdesc = reinterpret_cast(dmarxdesc->Buffer2NextDescAddr); - buffer = reinterpret_cast(dmarxdesc->Buffer1Addr); - - byteslefttocopy = byteslefttocopy - (ETH_RX_BUF_SIZE - bufferoffset); - payloadoffset = payloadoffset + (ETH_RX_BUF_SIZE - bufferoffset); - bufferoffset = 0; - } - /* Copy remaining data in pbuf */ - memcpy(static_cast(memory_manager->get_ptr(q)) + payloadoffset, static_cast(buffer) + bufferoffset, byteslefttocopy); - bufferoffset = bufferoffset + byteslefttocopy; - } - } - - /* Release descriptors to DMA */ - /* Point to first descriptor */ - dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc; - /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ - for (uint32_t i = 0; i < EthHandle.RxFrameInfos.SegCount; i++) { - dmarxdesc->Status |= ETH_DMARXDESC_OWN; - dmarxdesc = reinterpret_cast(dmarxdesc->Buffer2NextDescAddr); - } - - /* Clear Segment_Count */ - EthHandle.RxFrameInfos.SegCount = 0; - - /* When Rx Buffer unavailable flag is set: clear it and resume reception */ - if ((EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) { - /* Clear RBUS ETHERNET DMA flag */ - EthHandle.Instance->DMASR = ETH_DMASR_RBUS; - /* Resume DMA reception */ - EthHandle.Instance->DMARPDR = 0; - } - return 0; -} -#else // ETH_IP_VERSION_V2 -{ - ETH_BufferTypeDef RxBuff; - uint32_t frameLength = 0; - - if (HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK) { - if (HAL_ETH_GetRxDataLength(&EthHandle, &frameLength) != HAL_OK) { - tr_error("Error: returned by HAL_ETH_GetRxDataLength"); - return -1; - } - - /* Build Rx descriptor to be ready for next data reception */ - HAL_ETH_BuildRxDescriptors(&EthHandle); - - /* Invalidate data cache for ETH Rx Buffers */ - SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, frameLength); - - *buf = pbuf_alloc(PBUF_RAW, frameLength, PBUF_POOL); - if (*buf) { - pbuf_take((struct pbuf *)*buf, RxBuff.buffer, frameLength); - } - } else { - return -1; - } - - return 0; -} -#endif // ETH_IP_VERSION_V2 - -/** \brief Attempt to read a packet from the EMAC interface. - * - */ -void STM32_EMAC::packet_rx() -{ - /* move received packet into a new buf */ - while (1) { - emac_mem_buf_t *p = NULL; - RXLockMutex.lock(); - if (low_level_input(&p) < 0) { - RXLockMutex.unlock(); - break; - } - if (p) { - emac_link_input_cb(p); - } - RXLockMutex.unlock(); - } -} - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void STM32_EMAC::thread_function(void *pvParameters) -{ - static struct STM32_EMAC *stm32_enet = static_cast(pvParameters); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX, osFlagsWaitAny, osWaitForever); - - if (flags & FLAG_RX) { - stm32_enet->packet_rx(); - } - } -} - -/** - * This task checks phy link status and updates net status - */ -void STM32_EMAC::phy_task() -#ifndef ETH_IP_VERSION_V2 -{ - uint32_t status; - - if (HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &status) == HAL_OK) { - if ((emac_link_state_cb) && (status != 0xFFFF)) { - if ((status & PHY_LINKED_STATUS) && !(phy_status & PHY_LINKED_STATUS)) { - tr_info("emac_link_state_cb set to true"); - emac_link_state_cb(true); - } else if (!(status & PHY_LINKED_STATUS) && (phy_status & PHY_LINKED_STATUS)) { - tr_info("emac_link_state_cb set to false"); - emac_link_state_cb(false); - } - } - phy_status = status; - } else { - tr_error("HAL_ETH_ReadPHYRegister issue"); - } - -} -#else // ETH_IP_VERSION_V2 -{ - const int32_t status = _phy_get_state(); - const int32_t old_status = (int32_t)phy_status; - const bool is_up = _phy_is_up(status); - const bool was_up = _phy_is_up(old_status); - - if (is_up && !was_up) { - uint32_t duplex, speed; - ETH_MACConfigTypeDef MACConf; - - if (!_phy_get_duplex_and_speed(status, &speed, &duplex)) { - // Default - duplex = ETH_FULLDUPLEX_MODE; - speed = ETH_SPEED_10M; - } - - /* Get MAC Config MAC */ - HAL_ETH_GetMACConfig(&EthHandle, &MACConf); - MACConf.DuplexMode = duplex; - MACConf.Speed = speed; - HAL_ETH_SetMACConfig(&EthHandle, &MACConf); - HAL_ETH_Start_IT(&EthHandle); - } else if (was_up && !is_up) { - // Stop ETH - disable_interrupts(); - HAL_ETH_Stop(&EthHandle); - enable_interrupts(); - } - - if (emac_link_state_cb) { - if (is_up && !was_up) { - emac_link_state_cb(true); - tr_info("emac_link_state_cb set to true"); - } else if (!is_up && was_up) { - emac_link_state_cb(false); - tr_info("emac_link_state_cb set to false"); - } - } - - phy_status = (uint32_t)status; -} -#endif // ETH_IP_VERSION_V2 - -#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ - || defined (STM32F779xx) -/** - * workaround for the ETH RMII bug in STM32F76x and STM32F77x revA - * - * \param[in] netif the lwip network interface structure - */ - -/** \brief Worker thread. - * - * Woken by thread flags to receive packets or clean up transmit - * - * \param[in] pvParameters pointer to the interface data - */ -void STM32_EMAC::rmii_watchdog_thread_function(void *pvParameters) -{ - struct STM32_EMAC *stm32_enet = static_cast(pvParameters); - - while (1) { - /* some good packets are received */ - if (stm32_enet->EthHandle.Instance->MMCRGUFCR > 0) { - /* RMII Init is OK - would need service to terminate or suspend - * the thread */ - while (1) { - /* don't do anything anymore */ - osDelay(0xFFFFFFFF); - } - } else if (stm32_enet->EthHandle.Instance->MMCRFCECR > 10) { - /* ETH received too many packets with CRC errors, resetting RMII */ - SYSCFG->PMC &= ~SYSCFG_PMC_MII_RMII_SEL; - SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; - stm32_enet->EthHandle.Instance->MMCCR |= ETH_MMCCR_CR; - } else { - osDelay(100); - } - } -} -#endif - -void STM32_EMAC::enable_interrupts(void) -{ - HAL_NVIC_SetPriority(ETH_IRQn, 0x7, 0); - HAL_NVIC_EnableIRQ(ETH_IRQn); -} - -void STM32_EMAC::disable_interrupts(void) -{ - NVIC_DisableIRQ(ETH_IRQn); -} - -/** This returns a unique 6-byte MAC address, based on the device UID -* This function overrides hal/common/mbed_interface.c function -* @param mac A 6-byte array to write the MAC address -*/ - -void mbed_mac_address(char *mac) -{ - if (mbed_otp_mac_address(mac)) { - return; - } else { - mbed_default_mac_address(mac); - } - return; -} - -__weak uint8_t mbed_otp_mac_address(char *mac) -{ - return 0; -} - -void mbed_default_mac_address(char *mac) -{ - unsigned char ST_mac_addr[3] = {0x00, 0x80, 0xe1}; // default STMicro mac address - - // Read unic id -#if defined (TARGET_STM32F2) - uint32_t word0 = *(uint32_t *)0x1FFF7A10; -#elif defined (TARGET_STM32F4) - uint32_t word0 = *(uint32_t *)0x1FFF7A10; -#elif defined (TARGET_STM32F7) - uint32_t word0 = *(uint32_t *)0x1FF0F420; -#elif defined (TARGET_STM32H7) - uint32_t word0 = *(uint32_t *)0x1FF1E800; -#else -#error MAC address can not be derived from target unique Id -#endif - - mac[0] = ST_mac_addr[0]; - mac[1] = ST_mac_addr[1]; - mac[2] = ST_mac_addr[2]; - mac[3] = (word0 & 0x00ff0000) >> 16; - mac[4] = (word0 & 0x0000ff00) >> 8; - mac[5] = (word0 & 0x000000ff); - - return; -} - -bool STM32_EMAC::power_up() -{ - tr_info("power_up"); - - sleep_manager_lock_deep_sleep(); - - /* Initialize the hardware */ - if (!low_level_init_successful()) { - return false; - } - - /* Worker thread */ -#if MBED_CONF_MBED_TRACE_ENABLE - thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, MBED_CONF_STM32_EMAC_THREAD_STACKSIZE * 2, THREAD_PRIORITY, &thread_cb); -#else - thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, MBED_CONF_STM32_EMAC_THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb); -#endif - - - phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD, mbed::callback(this, &STM32_EMAC::phy_task)); - -#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ - || defined (STM32F779xx) - rmii_watchdog_thread = create_new_thread("stm32_rmii_watchdog", &STM32_EMAC::rmii_watchdog_thread_function, this, 128, THREAD_PRIORITY, &rmii_watchdog_thread_cb); -#endif - - /* Allow the PHY task to detect the initial link state and set up the proper flags */ - osDelay(10); - - enable_interrupts(); - - return true; -} - -uint32_t STM32_EMAC::get_mtu_size() const -{ - return STM_ETH_MTU_SIZE; -} - -uint32_t STM32_EMAC::get_align_preference() const -{ - return 0; -} - -void STM32_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, STM_ETH_IF_NAME, (size < sizeof(STM_ETH_IF_NAME)) ? size : sizeof(STM_ETH_IF_NAME)); -} - -uint8_t STM32_EMAC::get_hwaddr_size() const -{ - return STM_HWADDR_SIZE; -} - -bool STM32_EMAC::get_hwaddr(uint8_t *addr) const -{ - mbed_mac_address((char *)addr); - return true; -} - -void STM32_EMAC::set_hwaddr(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void STM32_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void STM32_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void STM32_EMAC::add_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void STM32_EMAC::remove_multicast_group(const uint8_t *addr) -{ - /* No-op at this stage */ -} - -void STM32_EMAC::set_all_multicast(bool all) -{ - /* No-op at this stage */ -} - -void STM32_EMAC::power_down() -{ - tr_info("power_down"); - - /* No-op at this stage */ - sleep_manager_unlock_deep_sleep(); -} - -void STM32_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -STM32_EMAC &STM32_EMAC::get_instance() -{ - static STM32_EMAC emac; - return emac; -} - -// Weak so a module can override -MBED_WEAK EMAC &EMAC::get_default_instance() -{ - return STM32_EMAC::get_instance(); -} - -#if defined(ETH_IP_VERSION_V2) -/******************************************************************************* - PHI IO Functions -*******************************************************************************/ - -/** - * @brief Initializes the MDIO interface GPIO and clocks. - * @param None - * @retval 0 if OK, -1 if ERROR - */ -static int32_t ETH_PHY_IO_Init(void) -{ - /* We assume that MDIO GPIO configuration is already done - in the ETH_MspInit() else it should be done here - */ - STM32_EMAC &emac = STM32_EMAC::get_instance(); - - /* Configure the MDIO Clock */ - HAL_ETH_SetMDIOClockRange(&emac.EthHandle); - - return 0; -} - -/** - * @brief De-Initializes the MDIO interface . - * @param None - * @retval 0 if OK, -1 if ERROR - */ -static int32_t ETH_PHY_IO_DeInit(void) -{ - return 0; -} - -/** - * @brief Read a PHY register through the MDIO interface. - * @param DevAddr: PHY port address - * @param RegAddr: PHY register address - * @param pRegVal: pointer to hold the register value - * @retval 0 if OK -1 if Error - */ -static int32_t ETH_PHY_IO_ReadReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t *pRegVal) -{ - STM32_EMAC &emac = STM32_EMAC::get_instance(); - if (HAL_ETH_ReadPHYRegister(&emac.EthHandle, DevAddr, RegAddr, pRegVal) != HAL_OK) { - return -1; - } - - return 0; -} - -/** - * @brief Write a value to a PHY register through the MDIO interface. - * @param DevAddr: PHY port address - * @param RegAddr: PHY register address - * @param RegVal: Value to be written - * @retval 0 if OK -1 if Error - */ -static int32_t ETH_PHY_IO_WriteReg(uint32_t DevAddr, uint32_t RegAddr, uint32_t RegVal) -{ - STM32_EMAC &emac = STM32_EMAC::get_instance(); - if (HAL_ETH_WritePHYRegister(&emac.EthHandle, DevAddr, RegAddr, RegVal) != HAL_OK) { - return -1; - } - - return 0; -} - -/** - * @brief Get the time in millisecons used for internal PHY driver process. - * @retval Time value - */ -static int32_t ETH_PHY_IO_GetTick(void) -{ - return HAL_GetTick(); -} - -/** - * Ethernet DMA transfer error callbacks - */ -void HAL_ETH_DMAErrorCallback(ETH_HandleTypeDef *heth) -{ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \ - "Error from ethernet HAL (HAL_ETH_DMAErrorCallback)\n"); -} - -/** - * Ethernet MAC transfer error callbacks - */ -void HAL_ETH_MACErrorCallback(ETH_HandleTypeDef *heth) -{ - MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER_ETHERNET, EIO), \ - "Error from ethernet HAL (HAL_ETH_MACErrorCallback)\n"); -} -#endif // ETH_IP_VERSION_V2 - -#endif /* DEVICE_EMAC */ diff --git a/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.h b/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.h deleted file mode 100644 index cfa6752..0000000 --- a/features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (c) 2017 ARM Limited - * Copyright (c) 2017 STMicroelectronics - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STM32_EMAC_H_ -#define STM32_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Mutex.h" - -class STM32_EMAC : public EMAC { -public: - STM32_EMAC(); - - static STM32_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. IP stack may or may not - * align link out memory buffer chains using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own HW - * address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is provided - * the stack would normally use that, but it could be overridden, eg for test - * purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - // Called from driver functions - ETH_HandleTypeDef EthHandle; - osThreadId_t thread; /**< Processing thread */ - -private: - bool low_level_init_successful(); - void packet_rx(); - int low_level_input(emac_mem_buf_t **buf); - static void thread_function(void *pvParameters); - static void rmii_watchdog_thread_function(void *pvParameters); - void phy_task(); - void enable_interrupts(); - void disable_interrupts(); - - mbed_rtos_storage_thread_t thread_cb; -#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\ - || defined (STM32F779xx) - mbed_rtos_storage_thread_t rmii_watchdog_thread_cb; - osThreadId_t rmii_watchdog_thread; /**< Watchdog processing thread */ -#endif - rtos::Mutex TXLockMutex;/**< TX critical section mutex */ - rtos::Mutex RXLockMutex;/**< RX critical section mutex */ - emac_link_input_cb_t emac_link_input_cb; /**< Callback for incoming data */ - emac_link_state_change_cb_t emac_link_state_cb; /**< Link state change callback */ - EMACMemoryManager *memory_manager; /**< Memory manager */ - - uint32_t phy_status; - int phy_task_handle; /**< Handle for phy task event */ -}; - -#endif /* STM32_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/mbed_lib.json b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/mbed_lib.json deleted file mode 100644 index a7d2bf6..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/mbed_lib.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "sl-eth", - "config": { - "rmii-location": { - "help": "Location number to use for the RMII pins, see chip datasheet", - "value": null - }, - "mdio-location": { - "help": "Location number to use for the MDIO pins, see chip datasheet", - "value": null - }, - "refclk-location": { - "help": "Location number to use for the REFCLK output from CMU (CLKOUTSEL2), see chip datasheet", - "value": null - }, - "phy-enable-pin": { - "help": "Pin attached to the PHY enable line", - "value": null - }, - "phy-power-pin": { - "help": "Pin used to switch on power to the PHY. If not defined, we assume the PHY is always powered.", - "value": null - } - }, - "target_overrides": { - "EFM32GG11_STK3701": { - "rmii-location": 1, - "mdio-location": 1, - "refclk-location": 5, - "phy-enable-pin": "PH7", - "phy-power-pin": "PI10" - } - } -} diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.cpp b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.cpp deleted file mode 100644 index 14c2115..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/***************************************************************************//** - * @file sl_emac.cpp - ******************************************************************************* - * @section License - * (C) Copyright 2018 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#include "device.h" - -#if defined(ETH_PRESENT) -#include "sl_emac_config.h" -#include "sl_emac.h" -#include "sl_eth_hw.h" -#include "sl_eth_phy.h" -#include "mbed_power_mgmt.h" - -#include - -#include "mbed-trace/mbed_trace.h" -#define TRACE_GROUP "SEth" - -#define FLAG_TX 1 -#define FLAG_RX 2 -#define FLAG_POLL 4 - -// ----------------------------------------------------------------------------- -// Setup -// ----------------------------------------------------------------------------- -bool SL_EMAC::power_up() -{ - // If the worker thread doesn't exist, launch it - if(thread == 0) { - /* Worker thread */ - osThreadAttr_t attr = {0}; - attr.name = "sl_emac_thread"; - attr.stack_mem = malloc(SL_ETH_THREAD_STACKSIZE); - attr.cb_mem = &thread_cb; - attr.stack_size = SL_ETH_THREAD_STACKSIZE; - attr.cb_size = sizeof(mbed_rtos_storage_thread_t); - attr.priority = SL_ETH_THREAD_PRIORITY; - thread = osThreadNew(&this->eth_thread, this, &attr); - } - - // Can't turn off HF clock as long as Ethernet is active - sleep_manager_lock_deep_sleep(); - - // Bring up data structures - data_init(); - - // Bring up clocks - sl_eth_hw_init(); - - // Point to RX queue - ETH->RXQPTR = (uint32_t)rx_bds; - ETH->DMACFG = (ETH->DMACFG & ~_ETH_DMACFG_RXBUFSIZE_MASK) - | ((SL_ETH_RX_BUF_SIZE/64) << _ETH_DMACFG_RXBUFSIZE_SHIFT); - - // Set up MAC address - uint8_t addr[6]; - get_hwaddr(addr); - set_hwaddr(addr); - - ETH->IFCR |= _ETH_IFCR_MASK; - ETH->RXSTATUS = 0xFFFFFFFF; - ETH->TXSTATUS = 0xFFFFFFFF; - ETH->IENS = ETH_IENS_RXCMPLT | - ETH_IENS_RXUSEDBITREAD | - ETH_IENS_TXCMPLT | - ETH_IENS_TXUNDERRUN | - ETH_IENS_RTRYLMTORLATECOL | - ETH_IENS_TXUSEDBITREAD | - ETH_IENS_AMBAERR | - ETH_IENS_MNGMNTDONE; - - ETH->NETWORKCFG |= ETH_NETWORKCFG_FCSREMOVE | - ETH_NETWORKCFG_UNICASTHASHEN | - ETH_NETWORKCFG_MULTICASTHASHEN | - ETH_NETWORKCFG_RXCHKSUMOFFLOADEN; - - ETH->NETWORKCFG |= ETH_NETWORKCFG_FULLDUPLEX | - ETH_NETWORKCFG_SPEED; - - ETH->DMACFG |= _ETH_DMACFG_AMBABRSTLEN_MASK | - ETH_DMACFG_FRCDISCARDONERR | - ETH_DMACFG_TXPBUFTCPEN; - - ETH->DMACFG &= ~ETH_DMACFG_HDRDATASPLITEN; - - ETH->NETWORKCTRL |= ETH_NETWORKCTRL_ENBTX | - ETH_NETWORKCTRL_ENBRX | - ETH_NETWORKCTRL_MANPORTEN; - - phy_init(); - - NVIC_EnableIRQ(ETH_IRQn); - - up = true; - - tr_debug("Link booted"); - - osThreadFlagsSet(thread, FLAG_POLL); - - return true; -} - -void SL_EMAC::power_down() -{ - up = false; - - tr_debug("Link coming down, waiting for TX to be done."); - - tx_sem.acquire(); - - NVIC_DisableIRQ(ETH_IRQn); - - sl_eth_hw_deinit(); - - data_deinit(); - - /* link is down */ - if(connected && emac_link_state_cb) { - emac_link_state_cb(false); - } - connected = false; - - tr_debug("Link down"); - - // Ethernet went down, HF clock is no longer required here - sleep_manager_unlock_deep_sleep(); -} - -void SL_EMAC::data_init(void) -{ - size_t i; - - /* Allocate a full-frame buffer for each RX BD and set up said BD */ - for(i = 0; i < SL_ETH_NUM_RX_BD; i++) { - rx_bufs[i] = memory_manager->alloc_heap(SL_ETH_RX_BUF_SIZE, SL_ETH_ALIGN); - rx_bds[i].addr = ((uint32_t)memory_manager->get_ptr(rx_bufs[i])) & ~0x3; - if(i == SL_ETH_NUM_RX_BD-1) { - rx_bds[i].addr |= 0x2; - } - rx_bds[i].status = 0; - } - - /* Set up TX BDs */ - tx_buf = (emac_mem_buf_t*)NULL; - for(i = 0; i < SL_ETH_NUM_TX_BD; i++) { - tx_bds[i].addr = 0; - tx_bds[i].status = 0; - if(i == SL_ETH_NUM_TX_BD-1) { - tx_bds[i].status |= (0x1 << 30); - } - } - - /* Start RX reception at index 0 */ - rx_idx = 0; -} - -void SL_EMAC::data_deinit(void) -{ - for(size_t i = 0; i < SL_ETH_NUM_RX_BD; i++) { - memory_manager->free(rx_bufs[i]); - } -} - -// ----------------------------------------------------------------------------- -// IRQ & IRQ de-escalation logic -// ----------------------------------------------------------------------------- -/* IRQ handler for ethernet interrupts */ -void ETH_IRQHandler(void) -{ - uint32_t int_clr = 0; - uint32_t int_status = ETH->IFCR; - uint32_t txdone_mask = ETH_IFCR_TXCMPLT | - ETH_IFCR_TXUNDERRUN | - ETH_IFCR_RTRYLMTORLATECOL | - ETH_IFCR_TXUSEDBITREAD | - ETH_IFCR_AMBAERR; - uint32_t rxdone_mask = ETH_IFCR_RXCMPLT | - ETH_IFCR_RXUSEDBITREAD; - - - SL_EMAC &emac = SL_EMAC::get_instance(); - - if(int_status & rxdone_mask) { - if (emac.thread) { - osThreadFlagsSet(emac.thread, FLAG_RX); - } - int_clr |= rxdone_mask; - } - - if(int_status & txdone_mask) { - if (emac.thread) { - osThreadFlagsSet(emac.thread, FLAG_TX); - } - int_clr |= txdone_mask; - } - - int_clr |= ETH_IFCR_MNGMNTDONE; - ETH->IFCR = int_clr; -} - -void SL_EMAC::eth_thread(void* instance) -{ - struct SL_EMAC *emac = static_cast(instance); - - for (;;) { - uint32_t flags = osThreadFlagsWait(FLAG_RX|FLAG_TX|FLAG_POLL, osFlagsWaitAny, SL_ETH_LINK_POLL_PERIOD_MS); - if ((flags == osFlagsErrorTimeout) && emac->up) { - // Rather than calling strictly every period, we call when idle - // for that period - hopefully good enough. We run this task - // from lwIP's thread rather than our RX/TX thread, as PHY reads can - // be slow, and we don't want them to interfere with data pumping. - // This is analogous to the way the PHY polling works in the Nanostack - // version of the driver - emac->link_state_poll(); - continue; - } - - if((flags & FLAG_POLL)) { - emac->link_state_poll(); - continue; - } - - MBED_ASSERT((flags & osFlagsError) == 0); - - /* Packet received */ - if ((flags & FLAG_RX) && emac->up) { - /* Find packets in the RX BD chain which have been fully received. Feed the - * corresponding buffer upstream, and attach a new buffer to the BD. */ - while(emac->rx_bds[emac->rx_idx].addr & 0x1) { - /* DMA has relinquished control over this packet */ - emac_mem_buf_t* buf = emac->rx_bufs[emac->rx_idx]; - emac->memory_manager->set_len(buf, emac->rx_bds[emac->rx_idx].status & 0x1FFF); - - tr_debug("Received packet of size %d", emac->memory_manager->get_len(buf)); - /* Attempt to queue new buffer */ - emac_mem_buf_t* temp_rxbuf = emac->memory_manager->alloc_heap(SL_ETH_RX_BUF_SIZE, 4); - if (NULL == temp_rxbuf) { - /* out of memory, drop packet */ - tr_warn("Packet index %d dropped for OOM", - emac->rx_idx); - emac->rx_bds[emac->rx_idx].addr &= ~0x1; - } else { - emac->rx_bufs[emac->rx_idx] = temp_rxbuf; - - emac->rx_bds[emac->rx_idx].status = 0; - if(emac->rx_bds[emac->rx_idx].addr & 0x2) { - emac->rx_bds[emac->rx_idx].addr = (uint32_t)emac->memory_manager->get_ptr(temp_rxbuf) | 0x2; - } else { - emac->rx_bds[emac->rx_idx].addr = (uint32_t)emac->memory_manager->get_ptr(temp_rxbuf); - } - - /* pass all packets to ethernet_input, which decides what packets it supports */ - if(emac->emac_link_input_cb) { - emac->emac_link_input_cb(buf); - } - } - emac->rx_idx = (emac->rx_idx + 1) % SL_ETH_NUM_RX_BD; - } - } - - /* Packet transmission done */ - if (flags & FLAG_TX) { - /* Free the buffer */ - if(emac->tx_buf != NULL) { - emac->memory_manager->free(emac->tx_buf); - emac->tx_buf = NULL; - } - - /* Signal TX thread(s) we're ready to start TX'ing */ - emac->tx_sem.release(); - } - } -} - -// ----------------------------------------------------------------------------- -// PHY manipulation -// ----------------------------------------------------------------------------- -void SL_EMAC::phy_init(void) -{ - uint8_t phy_addr = 0; - uint16_t regid1, regid2; - /* PHY has been enabled by hw_init. Figure out address first */ - for(; phy_addr < 32; phy_addr++) { - read_phy(PHY_PHYSID1, ®id1); - read_phy(PHY_PHYSID2, ®id2); - - if (((regid1 == 0x0000u) && (regid2 == 0x0000u)) || - ((regid1 == 0x3FFFu) && (regid2 == 0x0000u)) || - ((regid1 == 0x0000u) && (regid2 == 0x3FFFu)) || - ((regid1 == 0x3FFFu) && (regid2 == 0x3FFFu)) || - ((regid1 == 0xFFFFu) && (regid2 == 0x0000u)) || - ((regid1 == 0x0000u) && (regid2 == 0xFFFFu)) || - ((regid1 == 0x3FFFu) && (regid2 == 0xFFFFu)) || - ((regid1 == 0xFFFFu) && (regid2 == 0xFFFFu))) { - continue; - } else { - break; - } - } - - if(phy_addr >= 32) { - /* no PHY found */ - this->phy_addr = 0xFF; - return; - } else { - this->phy_addr = phy_addr; - } - - /* Reset PHY */ - write_phy(PHY_BMCR, BMCR_RESET); - read_phy(PHY_BMCR, ®id1); - - /* wait for PHY to come out of reset */ - while(regid1 & BMCR_RESET) { - osDelay(2); - read_phy(PHY_BMCR, ®id1); - } - - /* Enable PHY */ - if(regid1 & BMCR_PDOWN) { - write_phy(PHY_BMCR, regid1 & (~BMCR_PDOWN)); - } - - /* Set up auto-negotiation */ - read_phy(PHY_BMCR, ®id1); - regid1 |= BMCR_ANENABLE | BMCR_ANRESTART; - write_phy(PHY_BMCR, regid1); -} - -void SL_EMAC::write_phy(uint8_t reg_addr, uint16_t data) -{ - unsigned int timeout; - - ETH->PHYMNGMNT = ETH_PHYMNGMNT_WRITE0_DEFAULT - | ETH_PHYMNGMNT_WRITE1 - | (0x01 << _ETH_PHYMNGMNT_OPERATION_SHIFT) - | ((phy_addr << _ETH_PHYMNGMNT_PHYADDR_SHIFT) - & _ETH_PHYMNGMNT_PHYADDR_MASK) - | ((reg_addr << _ETH_PHYMNGMNT_REGADDR_SHIFT) - & _ETH_PHYMNGMNT_REGADDR_MASK) - | (0x2 << _ETH_PHYMNGMNT_WRITE10_SHIFT) - | (data & _ETH_PHYMNGMNT_PHYRWDATA_MASK); - - for(timeout = 0; timeout < 10000u; timeout++) { - if(ETH->NETWORKSTATUS & ETH_NETWORKSTATUS_MANDONE) { - break; - } - } -} - -void SL_EMAC::read_phy(uint8_t reg_addr, uint16_t *data) -{ - unsigned int timeout; - - ETH->PHYMNGMNT = ETH_PHYMNGMNT_WRITE0_DEFAULT - | ETH_PHYMNGMNT_WRITE1 - | (0x02 << _ETH_PHYMNGMNT_OPERATION_SHIFT) - | ((phy_addr << _ETH_PHYMNGMNT_PHYADDR_SHIFT) - & _ETH_PHYMNGMNT_PHYADDR_MASK) - | ((reg_addr << _ETH_PHYMNGMNT_REGADDR_SHIFT) - & _ETH_PHYMNGMNT_REGADDR_MASK) - | (0x2 << _ETH_PHYMNGMNT_WRITE10_SHIFT); - - for(timeout = 0; timeout < 10000u; timeout++) { - if(ETH->NETWORKSTATUS & ETH_NETWORKSTATUS_MANDONE) { - break; - } - } - - *data = ETH->PHYMNGMNT & _ETH_PHYMNGMNT_PHYRWDATA_MASK; -} - -void SL_EMAC::link_state_poll(void) -{ - uint16_t phy_val, link_val; - - /* read BMSR twice, since it needs to latch */ - read_phy(PHY_BMSR, &phy_val); - read_phy(PHY_BMSR, &phy_val); - - if((phy_val & BMSR_LSTATUS) == 0) { - /* link is down */ - tr_debug("link down"); - if(connected && emac_link_state_cb) { - emac_link_state_cb(false); - /* TODO: Reset all buffers here */ - /* For now, this is not a problem. In-transit buffers will - * still be sent the next time the link comes up, so the - * only impact is that we'd be sending stale packets. */ - } - connected = false; - return; - } - - /* link is up, get speed and duplex status */ - read_phy(PHY_ANAR, &phy_val); - read_phy(PHY_ANLPAR, &link_val); - - link_val &= (ANLPAR_100BASE4 | - ANLPAR_100FULL | - ANLPAR_100HALF | - ANLPAR_10FULL | - ANLPAR_10HALF); - - phy_val &= link_val; - - uint32_t old_link_state = ETH->NETWORKCFG & 0x3; - - if (phy_val >= ANLPAR_100FULL) { - /* 100 mbit full duplex */ - if (old_link_state != 0x3 || !connected) { - tr_debug("renegotiated to 100 full"); - ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x3; - } - } else if (phy_val >= ANLPAR_100HALF) { - /* 100 mbit half duplex */ - if (old_link_state != 0x1 || !connected) { - tr_debug("renegotiated to 100 half"); - ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x1; - } - } else if (phy_val >= ANLPAR_10FULL) { - /* 10 mbit full duplex */ - if (old_link_state != 0x2 || !connected) { - tr_debug("renegotiated to 10 full"); - ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x2; - } - } else { - /* 10 mbit half duplex */ - if (old_link_state != 0x0 || !connected) { - tr_debug("renegotiated to 10 half"); - ETH->NETWORKCFG = (ETH->NETWORKCFG & ~0x3) | 0x0; - } - } - - if(!connected && emac_link_state_cb) { - tr_debug("link up"); - emac_link_state_cb(true); - } - connected = true; -} - -// ----------------------------------------------------------------------------- -// Receive -// ----------------------------------------------------------------------------- - -/* Handled inside processing thread */ - -// ----------------------------------------------------------------------------- -// Send -// ----------------------------------------------------------------------------- -bool SL_EMAC::link_out(emac_mem_buf_t *buf) -{ - size_t num_bufs = 1, i; - emac_mem_buf_t * next = buf; - - /* If the link is down (or going down), don't even attempt sending anything */ - if(!up) { - tr_debug("Trying to send a packet while link is down"); - memory_manager->free(buf); - return false; - } - - /* Figure out how many buffers the buffer consists of */ - while((next = memory_manager->get_next(next)) != (emac_mem_buf_t*)NULL) { - num_bufs++; - } - - if(num_bufs >= SL_ETH_NUM_TX_BD) { - /* We've been passed more chained buffers than we can handle */ - tr_err("More TX buffers passed than provisioned!"); - memory_manager->free(buf); - return false; - } - - /* Wait for previous packet to finish transmitting */ - if (!tx_sem.try_acquire_for(100)) { - tr_warn("TX process didn't complete within 100ms"); - memory_manager->free(buf); - return false; - } - - tr_debug("Sending packet of %d bytes over %d buffers", memory_manager->get_total_len(buf), num_bufs); - - /* Set up TX descriptors with buffer, keep track of buffer reference */ - tx_buf = buf; - for(i = 0; i < num_bufs; i++) { - uint32_t statusword = memory_manager->get_len(buf) & 0x3FFF; - - if(i == (SL_ETH_NUM_TX_BD-1)) { - /* Mark as last BD in list */ - statusword |= (0x1 << 30); - } - if(i == num_bufs - 1) { - /* Mark as last BD for this frame */ - statusword |= (0x1 << 15); - } - - tx_bds[i].addr = (uint32_t)memory_manager->get_ptr(buf); - tx_bds[i].status = statusword; - - buf = memory_manager->get_next(buf); - } - - /* (Re-)Kick off ETH TX */ - ETH->TXQPTR = (uint32_t)tx_bds; - ETH->NETWORKCTRL |= ETH_NETWORKCTRL_TXSTRT; - return true; -} - -// ----------------------------------------------------------------------------- -// Multicast manipulation -// ----------------------------------------------------------------------------- -static uint8_t sl_eth_calc_hash(const uint8_t* const mac) -{ - return (uint8_t)(( (mac[0] & 0x3F) & 0x3F) - ^ ((((mac[0] >> 6) & 0x3) | ((mac[1] & 0xF) << 2)) & 0x3F) - ^ ((((mac[1] >> 4) & 0xF) | ((mac[2] & 0x3) << 4)) & 0x3F) - ^ ((((mac[2] >> 2) & 0x3F)) & 0x3F) - ^ ((mac[3] & 0x3F) & 0x3F) - ^ ((((mac[3] >> 6) & 0x3) | ((mac[4] & 0xF) << 2)) & 0x3F) - ^ ((((mac[4] >> 4) & 0xF) | ((mac[5] & 0x3) << 4)) & 0x3F) - ^ ((((mac[5] >> 2) & 0x3F)) & 0x3F)); -} - -void SL_EMAC::add_multicast_group(const uint8_t *address) -{ - uint8_t bitnr; - /* Calculate bit number for hash of this address */ - bitnr = sl_eth_calc_hash(address); - /* Increment refcnt */ - if (mcast_hash_refcnt[bitnr] == 0) { - if(bitnr > 31) { - ETH->HASHTOP |= (0x1 << (bitnr - 32)); - } else { - ETH->HASHBOTTOM |= (0x1 << bitnr); - } - } - mcast_hash_refcnt[bitnr]++; -} - -void SL_EMAC::remove_multicast_group(const uint8_t *address) -{ - uint8_t bitnr; - /* Calculate bit number for hash of this address */ - bitnr = sl_eth_calc_hash(address); - /* Decrement refcnt, remove bit if 0 */ - if(mcast_hash_refcnt[bitnr] == 1) { - mcast_hash_refcnt[bitnr] = 0; - if(bitnr > 31) { - ETH->HASHTOP &= ~(0x1 << (bitnr - 32)); - } else { - ETH->HASHBOTTOM &= ~(0x1 << bitnr); - } - } else { - mcast_hash_refcnt[bitnr]--; - } -} - -void SL_EMAC::set_all_multicast(bool all) -{ - uint32_t bottom = 0, top = 0; - - if(all == true) { - /* temporarily allow all packets to get processed */ - tr_debug("Accept all multicast packets"); - top = 0xFFFFFFFFUL; - bottom = 0xFFFFFFFFUL; - } else { - /* Revert to what was in the refcount */ - tr_debug("Revert to multicast filtering"); - size_t i = 0; - for(; i < 32; i++) { - if(mcast_hash_refcnt[i] > 0) { - bottom |= (1 << i); - } - } - for(; i < 64; i++) { - if(mcast_hash_refcnt[i-32] > 0) { - top |= (1 << (i-32)); - } - } - } - - /* Commit to peripheral */ - ETH->HASHTOP = top; - ETH->HASHBOTTOM = bottom; -} - -// ----------------------------------------------------------------------------- -// MAC manipulation -// ----------------------------------------------------------------------------- -uint8_t SL_EMAC::get_hwaddr_size() const -{ - // Ethernet uses EUI48 - return 6; -} - -bool SL_EMAC::get_hwaddr(uint8_t *addr) const -{ - if (DEVINFO->EUI48L != 0xFFFFFFFF) { - addr[0] = DEVINFO->EUI48H >> 8; - addr[1] = DEVINFO->EUI48H >> 0; - addr[2] = DEVINFO->EUI48L >> 24; - addr[3] = DEVINFO->EUI48L >> 16; - addr[4] = DEVINFO->EUI48L >> 8; - addr[5] = DEVINFO->EUI48L >> 0; - } else { - addr[0] = DEVINFO->UNIQUEH >> 24; - addr[1] = DEVINFO->UNIQUEH >> 16; - addr[2] = DEVINFO->UNIQUEH >> 8; - addr[3] = DEVINFO->UNIQUEL >> 16; - addr[4] = DEVINFO->UNIQUEL >> 8; - addr[5] = DEVINFO->UNIQUEL >> 0; - } - return true; -} - -void SL_EMAC::set_hwaddr(const uint8_t *addr) -{ - tr_debug("Setting MAC address %02x:%02x:%02x:%02x:%02x:%02x", - addr[0], - addr[1], - addr[2], - addr[3], - addr[4], - addr[5]); - ETH->SPECADDR1BOTTOM = ((uint32_t)addr[0] << (0)) | - ((uint32_t)addr[1] << (8)) | - ((uint32_t)addr[2] << (16))| - ((uint32_t)addr[3] << (24)); - - ETH->SPECADDR1TOP = ((uint32_t)addr[4] << (0)) | - ((uint32_t)addr[5] << (8)); -} - -// ----------------------------------------------------------------------------- -// Boilerplate -// ----------------------------------------------------------------------------- -SL_EMAC::SL_EMAC() - : thread(0), - tx_sem(1, 1), - phy_addr(0xFF), - rx_idx(0), - mcast_hash_refcnt(), - emac_link_input_cb(NULL), - emac_link_state_cb(NULL), - memory_manager(NULL), - connected(false), - up(false) -{ - -} - -uint32_t SL_EMAC::get_mtu_size() const -{ - return SL_ETH_MTU; -} - -uint32_t SL_EMAC::get_align_preference() const -{ - return SL_ETH_ALIGN; -} - -void SL_EMAC::get_ifname(char *name, uint8_t size) const -{ - memcpy(name, SL_ETH_IF_NAME, (size < sizeof(SL_ETH_IF_NAME)) ? size : sizeof(SL_ETH_IF_NAME)); -} - -void SL_EMAC::set_link_input_cb(emac_link_input_cb_t input_cb) -{ - emac_link_input_cb = input_cb; -} - -void SL_EMAC::set_link_state_cb(emac_link_state_change_cb_t state_cb) -{ - emac_link_state_cb = state_cb; -} - -void SL_EMAC::set_memory_manager(EMACMemoryManager &mem_mngr) -{ - memory_manager = &mem_mngr; -} - -SL_EMAC &SL_EMAC::get_instance() { - static SL_EMAC emac; - return emac; -} - -MBED_WEAK EMAC &EMAC::get_default_instance() { - return SL_EMAC::get_instance(); -} - -#endif //ETH_PRESENT diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.h b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.h deleted file mode 100644 index 4fdc6d7..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac.h +++ /dev/null @@ -1,256 +0,0 @@ -/***************************************************************************//** - * @file sl_eth_phy.h - ******************************************************************************* - * @section License - * modifications (C) Copyright 2018 Silicon Labs, http://www.silabs.com - * original Copyright (c) 2015 ARM Limited - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#ifndef SL_EMAC_H_ -#define SL_EMAC_H_ - -#include "EMAC.h" -#include "rtos/Semaphore.h" -#include "rtos/Mutex.h" - -class SL_EMAC : public EMAC { -public: - SL_EMAC(); - - static SL_EMAC &get_instance(); - - /** - * Return maximum transmission unit - * - * @return MTU in bytes - */ - virtual uint32_t get_mtu_size() const; - - /** - * Gets memory buffer alignment preference - * - * Gets preferred memory buffer alignment of the Emac device. - * IP stack may or may not align link out memory buffer chains - * using the alignment. - * - * @return Memory alignment requirement in bytes - */ - virtual uint32_t get_align_preference() const; - - /** - * Return interface name - * - * @param name Pointer to where the name should be written - * @param size Maximum number of character to copy - */ - virtual void get_ifname(char *name, uint8_t size) const; - - /** - * Returns size of the underlying interface HW address size. - * - * @return HW address size in bytes - */ - virtual uint8_t get_hwaddr_size() const; - - /** - * Return interface-supplied HW address - * - * Copies HW address to provided memory, @param addr has to be of correct - * size see @a get_hwaddr_size - * - * HW address need not be provided if this interface does not have its own - * HW address configuration; stack will choose address from central system - * configuration if the function returns false and does not write to addr. - * - * @param addr HW address for underlying interface - * @return true if HW address is available - */ - virtual bool get_hwaddr(uint8_t *addr) const; - - /** - * Set HW address for interface - * - * Provided address has to be of correct size, see @a get_hwaddr_size - * - * Called to set the MAC address to actually use - if @a get_hwaddr is - * provided the stack would normally use that, but it could be overridden, - * eg for test purposes. - * - * @param addr Address to be set - */ - virtual void set_hwaddr(const uint8_t *addr); - - /** - * Sends the packet over the link - * - * That can not be called from an interrupt context. - * - * @param buf Packet to be send - * @return True if the packet was send successfully, False otherwise - */ - virtual bool link_out(emac_mem_buf_t *buf); - - /** - * Initializes the HW - * - * @return True on success, False in case of an error. - */ - virtual bool power_up(); - - /** - * Deinitializes the HW - * - */ - virtual void power_down(); - - /** - * Sets a callback that needs to be called for packets received for that - * interface - * - * @param input_cb Function to be register as a callback - */ - virtual void set_link_input_cb(emac_link_input_cb_t input_cb); - - /** - * Sets a callback that needs to be called on link status changes for given - * interface - * - * @param state_cb Function to be register as a callback - */ - virtual void set_link_state_cb(emac_link_state_change_cb_t state_cb); - - /** Add device to a multicast group - * - * @param address A multicast group hardware address - */ - virtual void add_multicast_group(const uint8_t *address); - - /** Remove device from a multicast group - * - * @param address A multicast group hardware address - */ - virtual void remove_multicast_group(const uint8_t *address); - - /** Request reception of all multicast packets - * - * @param all True to receive all multicasts - * False to receive only multicasts addressed to specified groups - */ - virtual void set_all_multicast(bool all); - - /** Sets memory manager that is used to handle memory buffers - * - * @param mem_mngr Pointer to memory manager - */ - virtual void set_memory_manager(EMACMemoryManager &mem_mngr); - - osThreadId_t thread; /** Ethernet driver thread */ - -private: - - /* Instance variables */ - - /** Semaphore protecting the TX state. - * Not a mutex since we're posting from IRQ - */ - rtos::Semaphore tx_sem; - /** (R)MII address where the detected PHY is residing */ - uint8_t phy_addr; - /** Index in RX queue for next packet to read */ - uint8_t rx_idx; - - /** Multicast mask reference count. Multicast filtering is done using a hash - * bit, so multiple multicast addresses might map to the same bit. That's - * why there needs to be a reference count for every bit in the 64-bit mask - */ - uint8_t mcast_hash_refcnt[64]; - - /** Local reference to the buffer that's in the process of being sent */ - emac_mem_buf_t *tx_buf; - /** List of current RX buffers, which autonomously get filled by the - * Ethernet peripheral. - */ - emac_mem_buf_t *rx_bufs[SL_ETH_NUM_RX_BD]; - - typedef struct { - uint32_t addr; - uint32_t status; - } sl_eth_bd_t; - - /** Internal list of DMA descriptors for the RX buffer pool */ - sl_eth_bd_t rx_bds[SL_ETH_NUM_RX_BD]; - /** Internal list of DMA descriptors to point to the current buffer being - * sent */ - sl_eth_bd_t tx_bds[SL_ETH_NUM_TX_BD]; - - /**< Processing thread */ - mbed_rtos_storage_thread_t thread_cb; - - /**< Callback for incoming data */ - emac_link_input_cb_t emac_link_input_cb; - /**< Callback for link state change */ - emac_link_state_change_cb_t emac_link_state_cb; - - /**< Memory manager instance */ - EMACMemoryManager *memory_manager; - - bool connected; - bool up; - - /* private functions */ - /** - * Thread to de-escalate Ethernet peripheral IRQ's - */ - static void eth_thread(void* instance); - - /** - * This function polls the (R)MII bus for the first - * available attached PHY chip, resets and enables the PHY - * in auto-negotiation mode. - */ - void phy_init(void); - - /** - * Write to detected PHY register. Nop if no PHY initialized. - */ - void write_phy(uint8_t reg_addr, uint16_t data); - - /** - * Read from detected PHY register. Nop if no PHY initialized. - */ - void read_phy(uint8_t reg_addr, uint16_t *data); - - /** - * This function checks the detected PHY for its - * current link status. Nop if no PHY was previously detected. - * Fires callback set by set_link_state_cb on change in link state. - */ - void link_state_poll(void); - - /** - * Initializes buffer structures - */ - void data_init(void); - - /** - * De-initializes buffer structures - */ - void data_deinit(void); -}; - -#endif /* SL_EMAC_H_ */ diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac_config.h b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac_config.h deleted file mode 100644 index 86c7d99..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_emac_config.h +++ /dev/null @@ -1,52 +0,0 @@ -/***************************************************************************//** - * @file sl_emac_config.h - ******************************************************************************* - * @section License - * (C) Copyright 2018 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#ifndef SL_EMAC_CONFIG_H -#define SL_EMAC_CONFIG_H -// ----------------------------------------------------------------------------- -// Config options -// ----------------------------------------------------------------------------- -/** Number of descriptors in receive list */ -#define SL_ETH_NUM_RX_BD (16) -/** Number of descriptors in transmit list */ -#define SL_ETH_NUM_TX_BD (8) -/** Size of one buffer in a buffer descriptor (must be multiple of 64) */ -#define SL_ETH_RX_BUF_SIZE (1536) -/** Timeout in milliseconds for polling the PHY link status */ -#define SL_ETH_LINK_POLL_PERIOD_MS (500) -/** Default Ethernet worker thread stack size in bytes */ -#include "mbed_trace.h" -#if MBED_CONF_MBED_TRACE_ENABLE == 1 -#define SL_ETH_THREAD_STACKSIZE (768) -#else -#define SL_ETH_THREAD_STACKSIZE (512) -#endif -/** Default Ethernet worker thread stack priority */ -#define SL_ETH_THREAD_PRIORITY (osPriorityHigh) -/** Name of interface */ -#define SL_ETH_IF_NAME "sl" -/** Required alignment (in bytes) for packet buffers */ -#define SL_ETH_ALIGN (16) -/** Link MTU */ -#define SL_ETH_MTU (1500) - -#endif /* SL_EMAC_CONFIG_H */ diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.c b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.c deleted file mode 100644 index ffb7f7f..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.c +++ /dev/null @@ -1,157 +0,0 @@ -/***************************************************************************//** - * @file sl_eth_hw.c - ******************************************************************************* - * @section License - * (C) Copyright 2017 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#include "sl_eth_hw.h" -#include "device.h" -#include "em_cmu.h" -#include "em_gpio.h" -#include "hal/gpio_api.h" - -#if defined(ETH_PRESENT) - -void sl_eth_hw_init(void) -{ - /* Turn on clocks to ETH */ - CMU_ClockEnable(cmuClock_HFPER, true); - CMU_ClockEnable(cmuClock_ETH, true); - CMU_ClockEnable(cmuClock_GPIO, true); - - /* Drive RMII from the MCU-side 50MHz clock */ - GPIO_PinModeSet(AF_CMU_CLK2_PORT(MBED_CONF_SL_ETH_REFCLK_LOCATION), - AF_CMU_CLK2_PIN(MBED_CONF_SL_ETH_REFCLK_LOCATION), - gpioModePushPull, 0); - CMU->CTRL |= CMU_CTRL_CLKOUTSEL2_HFXO; - CMU->ROUTELOC0 = (CMU->ROUTELOC0 & ~_CMU_ROUTELOC0_CLKOUT2LOC_MASK) | (MBED_CONF_SL_ETH_REFCLK_LOCATION << _CMU_ROUTELOC0_CLKOUT2LOC_SHIFT); - CMU->ROUTEPEN |= CMU_ROUTEPEN_CLKOUT2PEN; - - ETH->CTRL = ETH_CTRL_GBLCLKEN | ETH_CTRL_MIISEL_RMII; - - /* Set pins to ETH for RMII config */ - GPIO_PinModeSet(AF_ETH_RMIICRSDV_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIICRSDV_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeInput, 0); /* CRS_DV */ - GPIO_PinModeSet(AF_ETH_RMIITXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModePushPull, 0); /* TXD0 */ - GPIO_PinModeSet(AF_ETH_RMIITXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModePushPull, 0); /* TXD1 */ - GPIO_PinModeSet(AF_ETH_RMIITXEN_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXEN_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModePushPull, 0); /* TX_EN */ - GPIO_PinModeSet(AF_ETH_RMIIRXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeInput, 0); /* RXD0 */ - GPIO_PinModeSet(AF_ETH_RMIIRXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeInput, 0); /* RXD1 */ - GPIO_PinModeSet(AF_ETH_RMIIRXER_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXER_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeInput, 0); /* RX_ER */ - - /* Setup route locations and enable pins */ - ETH->ROUTELOC1 = (MBED_CONF_SL_ETH_RMII_LOCATION << _ETH_ROUTELOC1_RMIILOC_SHIFT) - | (MBED_CONF_SL_ETH_MDIO_LOCATION << _ETH_ROUTELOC1_MDIOLOC_SHIFT); - ETH->ROUTEPEN = ETH_ROUTEPEN_RMIIPEN | ETH_ROUTEPEN_MDIOPEN; - ETH->ROUTEPEN = ETH_ROUTEPEN_RMIIPEN | ETH_ROUTEPEN_MDIOPEN; - - /* Setup the MDIO pins */ - GPIO_PinModeSet(AF_ETH_MDIO_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), - AF_ETH_MDIO_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), - gpioModePushPull, 0); /* MDIO */ - GPIO_PinModeSet(AF_ETH_MDC_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), - AF_ETH_MDC_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), - gpioModePushPull, 0); /* MDC */ - - /* Enable the PHY on the STK */ -#if defined(MBED_CONF_SL_ETH_PHY_POWER_PIN) - gpio_t pwr_pin; - gpio_init_out_ex(&pwr_pin, MBED_CONF_SL_ETH_PHY_POWER_PIN, 1); -#endif - -#if defined(MBED_CONF_SL_ETH_PHY_ENABLE_PIN) - gpio_t en_pin; - gpio_init_out_ex(&en_pin, MBED_CONF_SL_ETH_PHY_ENABLE_PIN, 1); -#endif -} - -void sl_eth_hw_deinit(void) -{ - /* Turn off PHY */ -#if defined(MBED_CONF_SL_ETH_PHY_POWER_PIN) - gpio_t pwr_pin; - gpio_init(&pwr_pin, MBED_CONF_SL_ETH_PHY_ENABLE_PIN); - gpio_write(&pwr_pin, 0); - gpio_mode(&pwr_pin, Disabled); -#endif - -#if defined(MBED_CONF_SL_ETH_PHY_ENABLE_PIN) - gpio_t en_pin; - gpio_init(&en_pin, MBED_CONF_SL_ETH_PHY_POWER_PIN); - gpio_write(&en_pin, 0); - gpio_mode(&en_pin, Disabled); -#endif - - /* Turn off MAC */ - ETH->ROUTEPEN = 0; - ETH->CTRL = _ETH_CTRL_RESETVALUE; - - /* Turn off clock */ - CMU->CTRL &= ~CMU_CTRL_CLKOUTSEL2_HFXO; - CMU->ROUTEPEN &= ~CMU_ROUTEPEN_CLKOUT2PEN; - - CMU_ClockEnable(cmuClock_ETH, false); - - /* Set used pins back to disabled */ - GPIO_PinModeSet(AF_ETH_MDIO_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), - AF_ETH_MDIO_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), - gpioModeDisabled, 0); /* MDIO */ - GPIO_PinModeSet(AF_ETH_MDC_PORT(MBED_CONF_SL_ETH_MDIO_LOCATION), - AF_ETH_MDC_PIN(MBED_CONF_SL_ETH_MDIO_LOCATION), - gpioModeDisabled, 0); /* MDC */ - GPIO_PinModeSet(AF_ETH_RMIICRSDV_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIICRSDV_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* CRS_DV */ - GPIO_PinModeSet(AF_ETH_RMIITXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* TXD0 */ - GPIO_PinModeSet(AF_ETH_RMIITXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* TXD1 */ - GPIO_PinModeSet(AF_ETH_RMIITXEN_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIITXEN_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* TX_EN */ - GPIO_PinModeSet(AF_ETH_RMIIRXD0_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXD0_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* RXD0 */ - GPIO_PinModeSet(AF_ETH_RMIIRXD1_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXD1_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* RXD1 */ - GPIO_PinModeSet(AF_ETH_RMIIRXER_PORT(MBED_CONF_SL_ETH_RMII_LOCATION), - AF_ETH_RMIIRXER_PIN(MBED_CONF_SL_ETH_RMII_LOCATION), - gpioModeDisabled, 0); /* RX_ER */ - GPIO_PinModeSet(AF_CMU_CLK2_PORT(MBED_CONF_SL_ETH_REFCLK_LOCATION), - AF_CMU_CLK2_PIN(MBED_CONF_SL_ETH_REFCLK_LOCATION), - gpioModeDisabled, 0); /* REF_CLK */ -} - -#endif //ETH_PRESENT diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.h b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.h deleted file mode 100644 index ebca47f..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_hw.h +++ /dev/null @@ -1,44 +0,0 @@ -/***************************************************************************//** - * @file sl_eth_hw.h - ******************************************************************************* - * @section License - * (C) Copyright 2018 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#ifndef SL_ETH_HW_H -#define SL_ETH_HW_H - -#if defined(__cplusplus) -extern "C" { -#endif - -/** - * Sets up hardware pins and configures internal clocks - */ -void sl_eth_hw_init(void); - -/** - * Releases hardware pins and turns off internal clocks - */ -void sl_eth_hw_deinit(void); - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_phy.h b/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_phy.h deleted file mode 100644 index 3e76859..0000000 --- a/features/netsocket/emac-drivers/TARGET_Silicon_Labs/sl_eth_phy.h +++ /dev/null @@ -1,94 +0,0 @@ -/***************************************************************************//** - * @file sl_eth_phy.h - ******************************************************************************* - * @section License - * (C) Copyright 2017 Silicon Labs, http://www.silabs.com - ******************************************************************************* - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ -#ifndef __SL_ETH_PHY_H__ -#define __SL_ETH_PHY_H__ - -#define PHY_BMCR 0x00u /* Basic mode control reg. */ -#define PHY_BMSR 0x01u /* Basic mode status reg. */ -#define PHY_PHYSID1 0x02u /* PHYS ID 1 reg. */ -#define PHY_PHYSID2 0x03u /* PHYS ID 2 reg. */ -#define PHY_ANAR 0x04u /* Advertisement control reg. */ -#define PHY_ANLPAR 0x05u /* Link partner ability reg. */ -#define PHY_ANER 0x06u /* Expansion reg. */ -#define PHY_ANNPTR 0x07u /* Next page transmit reg. */ - -/* -------------- PHY_BMCR REGISTER BITS -------------- */ -#define BMCR_CTST (0x1 << 7) /* Collision test. */ -#define BMCR_FULLDPLX (0x1 << 8) /* Full duplex. */ -#define BMCR_ANRESTART (0x1 << 9) /* Auto negotiation restart. */ -#define BMCR_ISOLATE (0x1 << 10) /* Disconnect Phy from MII. */ -#define BMCR_PDOWN (0x1 << 11) /* Power down. */ -#define BMCR_ANENABLE (0x1 << 12) /* Enable auto negotiation. */ -#define BMCR_SPEED100 (0x1 << 13) /* Select 100Mbps. */ -#define BMCR_LOOPBACK (0x1 << 14) /* TXD loopback bits. */ -#define BMCR_RESET (0x1 << 15) /* Reset. */ - -/* -------------- PHY_BMSR REGISTER BITS -------------- */ -#define BMSR_ERCAP (0x1 << 0) /* Ext-reg capability. */ -#define BMSR_JCD (0x1 << 1) /* Jabber detected. */ -#define BMSR_LSTATUS (0x1 << 2) /* Link status. */ -#define BMSR_ANEGCAPABLE (0x1 << 3) /* Able to do auto-negotiation. */ -#define BMSR_RFAULT (0x1 << 4) /* Remote fault detected. */ -#define BMSR_ANEGCOMPLETE (0x1 << 5) /* Auto-negotiation complete. */ -#define BMSR_10HALF (0x1 << 11) /* Can do 10mbps, half-duplex. */ -#define BMSR_10FULL (0x1 << 12) /* Can do 10mbps, full-duplex. */ -#define BMSR_100HALF (0x1 << 13) /* Can do 100mbps, half-duplex. */ -#define BMSR_100FULL (0x1 << 14) /* Can do 100mbps, full-duplex. */ -#define BMSR_100BASE4 (0x1 << 15) /* Can do 100mbps, 4k packets. */ - -/* -------------- PHY_ANAR REGISTER BITS -------------- */ -#define ANAR_SLCT 0x001Fu /* Selector bits. */ -#define ANAR_CSMA DEF_BIT_04 /* Only selector supported. */ -#define ANAR_10HALF DEF_BIT_05 /* Try for 10mbps half-duplex. */ -#define ANAR_10FULL DEF_BIT_06 /* Try for 10mbps full-duplex. */ -#define ANAR_100HALF DEF_BIT_07 /* Try for 100mbps half-duplex. */ -#define ANAR_100FULL DEF_BIT_08 /* Try for 100mbps full-duplex. */ -#define ANAR_100BASE4 DEF_BIT_09 /* Try for 100mbps 4k packets. */ -#define ANAR_RFAULT DEF_BIT_13 /* Say we can detect faults. */ -#define ANAR_LPACK DEF_BIT_14 /* Ack link partners response. */ -#define ANAR_NPAGE DEF_BIT_15 /* Next page bit. */ - -#define ANAR_FULL (ANAR_100FULL | ANAR_10FULL | ANAR_CSMA) -#define ANAR_ALL (ANAR_100BASE4 | ANAR_100FULL | ANAR_10FULL | ANAR_100HALF | ANAR_10HALF) - -/* ------------- PHY_ANLPAR REGISTER BITS ------------- */ -#define ANLPAR_10HALF (0x1 << 5) /* Can do 10mbps half-duplex. */ -#define ANLPAR_10FULL (0x1 << 6) /* Can do 10mbps full-duplex. */ -#define ANLPAR_100HALF (0x1 << 7) /* Can do 100mbps half-duplex. */ -#define ANLPAR_100FULL (0x1 << 8) /* Can do 100mbps full-duplex. */ -#define ANLPAR_100BASE4 (0x1 << 9) /* Can do 100mbps 4k packets. */ -#define ANLPAR_RFAULT (0x1 << 13) /* Link partner faulted. */ -#define ANLPAR_LPACK (0x1 << 14) /* Link partner acked us. */ -#define ANLPAR_NPAGE (0x1 << 15) /* Next page bit. */ - -#define ANLPAR_DUPLEX (ANLPAR_10FULL | ANLPAR_100FULL) -#define ANLPAR_100 (ANLPAR_100FULL | ANLPAR_100HALF | ANLPAR_100BASE4) - -/* -------------- PHY_ANER REGISTER BITS -------------- */ -#define ANER_NWAY (0x1 << 0) /* Can do N-way auto-negotiation. */ -#define ANER_LCWP (0x1 << 1) /* Got new RX page code word. */ -#define ANER_ENABLENPAGE (0x1 << 2) /* This enables npage words. */ -#define ANER_NPCAPABLE (0x1 << 3) /* Link partner supports npage. */ -#define ANER_MFAULTS (0x1 << 4) /* Multiple faults detected. */ - -#endif