mirror of https://github.com/ARMmbed/mbed-os.git
Merge branch 'cm3ds_emac' of git://github.com/kapi90/mbed-os into dev_rollup
commit
0217f69511
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "smsc9220-emac",
|
||||
"config": {
|
||||
"rx-ring-len": 1,
|
||||
"tx-ring-len": 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* 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 <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
|
||||
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(message_length, SMSC9220_BUFF_ALIGNMENT);
|
||||
|
||||
if (p != NULL) {
|
||||
_RXLockMutex.lock();
|
||||
smsc9220_receive_by_chunks(dev, (char*)_memory_manager->get_ptr(p),
|
||||
_memory_manager->get_len(p));
|
||||
_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<SMSC9220_EMAC *>(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<uint32_t>(_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));
|
||||
if (error != SMSC9220_ERROR_NONE) {
|
||||
_TXLockMutex.unlock();
|
||||
return false;
|
||||
}
|
||||
_TXLockMutex.unlock();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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 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, &wait_ms);
|
||||
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 */
|
||||
wait_ms(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();
|
||||
}
|
|
@ -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_ */
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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_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"
|
||||
|
||||
/** \brief Defines for receiver thread */
|
||||
#define FLAG_RX 1U
|
||||
#define LINK_STATUS_THREAD_PRIORITY (osPriorityNormal)
|
||||
#define LINK_STATUS_THREAD_STACKSIZE 2048U
|
||||
#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 */
|
|
@ -58,4 +58,10 @@
|
|||
#define ARM_UART3
|
||||
#define ARM_UART4
|
||||
|
||||
/* SMSC9220 Ethernet */
|
||||
#ifdef COMPONENT_SMSC9220
|
||||
#define SMSC9220_ETH
|
||||
#define SMSC9220_Ethernet_Interrupt_Handler ETHERNET_IRQHandler
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_DEVICE_CFG_H__ */
|
||||
|
|
|
@ -1,746 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2017-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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Code implementation file for the LAN Ethernet interface.
|
||||
*
|
||||
* This file is the based on mps2_ethernet_api and Selftest's ETH_MPS2.
|
||||
* MPS2 Selftest:https://silver.arm.com/browse/VEI10 ->
|
||||
* \ISCM-1-0\AN491\software\Selftest\v2m_mps2\
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mbed_retarget.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include "CM3DS.h"
|
||||
#include "smsc9220_eth.h"
|
||||
|
||||
#define REG_WRITE_TIME_OUT 50
|
||||
#define RESET_TIME_OUT 10
|
||||
#define PHY_RESET_TIME_OUT_MS 100
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
static unsigned int smsc9220_mac_regread(unsigned char regoffset, unsigned int *data);
|
||||
static unsigned int smsc9220_mac_regwrite(unsigned char regoffset, unsigned int data);
|
||||
static unsigned int smsc9220_phy_regread(unsigned char regoffset, unsigned int *data);
|
||||
static unsigned int smsc9220_phy_regwrite(unsigned char regoffset, unsigned int data);
|
||||
|
||||
static unsigned int smsc9220_read_id(void);
|
||||
static unsigned int smsc9220_soft_reset(void);
|
||||
static void smsc9220_set_txfifo(unsigned int val);
|
||||
static unsigned int smsc9220_wait_eeprom(void);
|
||||
static void smsc9220_init_irqs(void);
|
||||
static unsigned int smsc9220_check_phy(void);
|
||||
static unsigned int smsc9220_reset_phy(void);
|
||||
|
||||
static void smsc9220_advertise_cap(void);
|
||||
static void smsc9220_enable_xmit(void);
|
||||
static void smsc9220_enable_mac_xmit(void);
|
||||
static void smsc9220_enable_mac_recv(void);
|
||||
|
||||
/* SMSC9220 low-level operations */
|
||||
|
||||
/**
|
||||
* \brief Read MAC register.
|
||||
*
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[out] data Register value is read
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_mac_regread(unsigned char regoffset, unsigned int *data)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
unsigned int maccmd = 0;
|
||||
int time_out = REG_WRITE_TIME_OUT;
|
||||
|
||||
val = SMSC9220->MAC_CSR_CMD;
|
||||
if(!(val & ((unsigned int)1 << 31))) { /* Make sure there's no pending operation */
|
||||
maccmd |= regoffset;
|
||||
maccmd |= ((unsigned int)1 << 30); /* Indicates read */
|
||||
maccmd |= ((unsigned int)1 << 31); /* Start bit */
|
||||
SMSC9220->MAC_CSR_CMD = maccmd; /* Start operation */
|
||||
|
||||
do {
|
||||
val = SMSC9220->BYTE_TEST; /* A no-op read. */
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
} while(time_out && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31)));
|
||||
|
||||
if(!time_out) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
*data = SMSC9220->MAC_CSR_DATA;
|
||||
}
|
||||
} else {
|
||||
*data = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write MAC register.
|
||||
*
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[in] data Register value to write
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_mac_regwrite(unsigned char regoffset, unsigned int data)
|
||||
{
|
||||
unsigned int read = 0;
|
||||
unsigned int maccmd = 0;
|
||||
int time_out = REG_WRITE_TIME_OUT;
|
||||
|
||||
read = SMSC9220->MAC_CSR_CMD;
|
||||
if(!(read & ((unsigned int)1 << 31))) { /* Make sure there's no pending operation */
|
||||
SMSC9220->MAC_CSR_DATA = data; /* Store data. */
|
||||
maccmd |= regoffset;
|
||||
maccmd &= ~((unsigned int)1 << 30); /* Clear indicates write */
|
||||
maccmd |= ((unsigned int)1 << 31); /* Indicate start of operation */
|
||||
SMSC9220->MAC_CSR_CMD = maccmd;
|
||||
|
||||
do {
|
||||
read = SMSC9220->BYTE_TEST; /* A no-op read. */
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
} while(time_out && (SMSC9220->MAC_CSR_CMD & ((unsigned int)1 << 31)));
|
||||
|
||||
if(!time_out) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printf("Error: SMSC9220 MAC CSR is busy. No data written.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read PHY register.
|
||||
*
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[out] data Register value is read
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_phy_regread(unsigned char regoffset, unsigned int *data)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
unsigned int phycmd = 0;
|
||||
int time_out = REG_WRITE_TIME_OUT;
|
||||
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!(val & 1)) { /* Not busy */
|
||||
phycmd = 0;
|
||||
phycmd |= (1 << 11); /* 1 to [15:11] */
|
||||
phycmd |= ((regoffset & 0x1F) << 6); /* Put regoffset to [10:6] */
|
||||
phycmd &= ~(1 << 1); /* Clear [1] indicates read. */
|
||||
phycmd |= (1 << 0); /* Set [0] indicates operation start */
|
||||
|
||||
if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
do {
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC,&val)) {
|
||||
return 1;
|
||||
}
|
||||
} while(time_out && (val & ((unsigned int)1 << 0)));
|
||||
|
||||
if (!time_out) {
|
||||
return 1;
|
||||
} else if (smsc9220_mac_regread(SMSC9220_MAC_MII_DATA, data)) {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
*data = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Write PHY register.
|
||||
*
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[in] data Register value to write
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_phy_regwrite(unsigned char regoffset, unsigned int data)
|
||||
{
|
||||
unsigned int val = 0;
|
||||
unsigned int phycmd = 0;
|
||||
int time_out = REG_WRITE_TIME_OUT;
|
||||
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &val)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(!(val & 1)) { /* Not busy */
|
||||
/* Load the data */
|
||||
if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_DATA, (data & 0xFFFF))) {
|
||||
return 1;
|
||||
}
|
||||
phycmd = 0;
|
||||
phycmd |= (1 << 11); /* 1 to [15:11] */
|
||||
phycmd |= ((regoffset & 0x1F) << 6); /* Put regoffset to [10:6] */
|
||||
phycmd |= (1 << 1); /* Set [1] indicates write. */
|
||||
phycmd |= (1 << 0); /* Set [0] indicates operation start */
|
||||
/* Start operation */
|
||||
if (smsc9220_mac_regwrite(SMSC9220_MAC_MII_ACC, phycmd)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
phycmd = 0;
|
||||
|
||||
do {
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_MII_ACC, &phycmd)){
|
||||
return 1;
|
||||
}
|
||||
} while(time_out && (phycmd & (1 << 0)));
|
||||
|
||||
if (!time_out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("Error: SMSC9220 MAC MII is busy. No data written.\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read SMSC9220 ID.
|
||||
*
|
||||
* \return ID number
|
||||
*/
|
||||
inline static unsigned int smsc9220_read_id(void)
|
||||
{
|
||||
return SMSC9220->ID_REV;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initiates a soft reset, returns failure or success.
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_soft_reset(void)
|
||||
{
|
||||
int time_out = RESET_TIME_OUT;
|
||||
|
||||
/* Soft reset */
|
||||
SMSC9220->HW_CFG |= 1;
|
||||
|
||||
do {
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
} while(time_out && (SMSC9220->HW_CFG & 1));
|
||||
|
||||
if (!time_out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set maximum transition unit by Tx fifo size.
|
||||
* Note: The MTU will be smaller by 512 bytes,
|
||||
* because the status uses this fixed space.
|
||||
*
|
||||
* \param[in] val Size of the fifo in kbytes, 2-14
|
||||
*/
|
||||
static void smsc9220_set_txfifo(unsigned int val)
|
||||
{
|
||||
/* 2kb minimum, 14kb maximum */
|
||||
if(val >= 2 && val <= 14) {
|
||||
SMSC9220->HW_CFG = val << 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for EEPROM to be ready to use.
|
||||
*
|
||||
* \return 0 if ready, 1 in case of timeout
|
||||
*/
|
||||
static unsigned int smsc9220_wait_eeprom(void)
|
||||
{
|
||||
int time_out = REG_WRITE_TIME_OUT;
|
||||
|
||||
do {
|
||||
wait_ms(1);
|
||||
time_out--;
|
||||
} while(time_out && (SMSC9220->E2P_CMD & ((unsigned int) 1 << 31)));
|
||||
|
||||
if (!time_out) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialise irqs
|
||||
*/
|
||||
static void smsc9220_init_irqs(void)
|
||||
{
|
||||
SMSC9220->INT_EN = 0x0;
|
||||
SMSC9220->INT_STS = 0xFFFFFFFF; /* clear all interrupts */
|
||||
SMSC9220->IRQ_CFG = 0x22000100; /* irq deassertion at 220 usecs and master IRQ enable. */
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check PHY ID registers.
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_check_phy(void)
|
||||
{
|
||||
unsigned int phyid1, phyid2;
|
||||
|
||||
if (smsc9220_phy_regread(SMSC9220_PHY_ID1,&phyid1)) {
|
||||
return 1;
|
||||
}
|
||||
if (smsc9220_phy_regread(SMSC9220_PHY_ID2,&phyid2)) {
|
||||
return 1;
|
||||
}
|
||||
return ((phyid1 == 0xFFFF && phyid2 == 0xFFFF) ||
|
||||
(phyid1 == 0x0 && phyid2 == 0x0));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset PHY
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static unsigned int smsc9220_reset_phy(void)
|
||||
{
|
||||
unsigned int read;
|
||||
|
||||
if(smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &read)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
read |= (1 << 15);
|
||||
if(smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, read)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Advertise all speeds and pause capabilities
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static void smsc9220_advertise_cap(void)
|
||||
{
|
||||
unsigned int aneg_adv = 0;
|
||||
|
||||
smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv);
|
||||
aneg_adv |= 0xDE0;
|
||||
|
||||
smsc9220_phy_regwrite(SMSC9220_PHY_ANEG_ADV, aneg_adv);
|
||||
smsc9220_phy_regread(SMSC9220_PHY_ANEG_ADV, &aneg_adv);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable trasmission
|
||||
*/
|
||||
inline static void smsc9220_enable_xmit(void)
|
||||
{
|
||||
SMSC9220->TX_CFG = 0x2;
|
||||
}
|
||||
|
||||
static void smsc9220_enable_mac_xmit(void)
|
||||
{
|
||||
unsigned int mac_cr = 0;
|
||||
|
||||
smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr);
|
||||
|
||||
mac_cr |= (1 << 3); /* xmit enable */
|
||||
mac_cr |= (1 << 28); /* Heartbeat disable */
|
||||
|
||||
smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable receive
|
||||
*/
|
||||
static void smsc9220_enable_mac_recv(void)
|
||||
{
|
||||
unsigned int mac_cr = 0;
|
||||
|
||||
smsc9220_mac_regread(SMSC9220_MAC_CR, &mac_cr);
|
||||
mac_cr |= (1 << 2); /* Recv enable */
|
||||
smsc9220_mac_regwrite(SMSC9220_MAC_CR, mac_cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check device ID.
|
||||
*
|
||||
* \return 0 in case of success, 1 otherwise
|
||||
*/
|
||||
static int smsc9220_check_id(void)
|
||||
{
|
||||
unsigned int id = smsc9220_read_id();
|
||||
|
||||
/* If bottom and top halves of the word are the same */
|
||||
if(((id >> 16) & 0xFFFF) == (id & 0xFFFF)) {
|
||||
return 1;
|
||||
}
|
||||
switch(((id >> 16) & 0xFFFF)) {
|
||||
case 0x9220:
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill the SMSC9220 TX FIFO with a number of words at an aligned
|
||||
* address.
|
||||
*
|
||||
* \param[in] data Pointer to the aligned data that should be sent.
|
||||
* \param[in] dwords_to_write Number of data words to write.
|
||||
*/
|
||||
static void fill_tx_fifo_aligned(unsigned int *data,
|
||||
unsigned int dwords_to_write)
|
||||
{
|
||||
while (dwords_to_write > 0) {
|
||||
SMSC9220->TX_DATA_PORT = *data;
|
||||
data++;
|
||||
dwords_to_write--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Fill the SMSC9220 TX FIFO with a number of words at an unaligned
|
||||
* address. This function ensures that loading words at that address will
|
||||
* not generate unaligned access which can trigger an exception to the
|
||||
* processor.
|
||||
*
|
||||
* \param[in] data Pointer to the unaligned data that should be sent.
|
||||
* \param[in] dwords_to_write Number of data words to write.
|
||||
*/
|
||||
static void fill_tx_fifo_unaligned(uint8_t *data, unsigned int dwords_to_write)
|
||||
{
|
||||
/*
|
||||
* Prevent unaligned word access from data pointer, 4 bytes are copied to
|
||||
* this variable for each word that need to be sent.
|
||||
*/
|
||||
unsigned int tx_data_port_tmp = 0;
|
||||
uint8_t *tx_data_port_tmp_ptr = (uint8_t *)&tx_data_port_tmp;
|
||||
|
||||
while (dwords_to_write > 0) {
|
||||
/* Keep the same endianness in data than in the temp variable */
|
||||
tx_data_port_tmp_ptr[0] = data[0];
|
||||
tx_data_port_tmp_ptr[1] = data[1];
|
||||
tx_data_port_tmp_ptr[2] = data[2];
|
||||
tx_data_port_tmp_ptr[3] = data[3];
|
||||
SMSC9220->TX_DATA_PORT = tx_data_port_tmp;
|
||||
data += 4;
|
||||
dwords_to_write--;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Public API
|
||||
*----------------------------------------------------------------------------*/
|
||||
int smsc9220_init(void)
|
||||
{
|
||||
unsigned int phyreset = 0;
|
||||
|
||||
if(smsc9220_check_id()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(smsc9220_soft_reset()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
smsc9220_set_txfifo(5);
|
||||
|
||||
/* Sets automatic flow control thresholds, and backpressure */
|
||||
/* threshold to defaults specified. */
|
||||
SMSC9220->AFC_CFG = 0x006E3740;
|
||||
|
||||
if(smsc9220_wait_eeprom()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Configure GPIOs as LED outputs. */
|
||||
SMSC9220->GPIO_CFG = 0x70070000;
|
||||
|
||||
smsc9220_init_irqs();
|
||||
|
||||
/* Configure MAC addresses here if needed. */
|
||||
|
||||
if(smsc9220_check_phy()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(smsc9220_reset_phy()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
wait_ms(PHY_RESET_TIME_OUT_MS);
|
||||
/* Checking whether phy reset completed successfully.*/
|
||||
if (smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &phyreset)) {
|
||||
return 1;
|
||||
}
|
||||
if(phyreset & (1 << 15)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
smsc9220_advertise_cap();
|
||||
smsc9220_establish_link(); /* bit [12] of BCONTROL seems self-clearing. */
|
||||
/* Although it's not so in the manual. */
|
||||
|
||||
/* Interrupt threshold */
|
||||
SMSC9220->FIFO_INT = 0xFF000000;
|
||||
|
||||
smsc9220_enable_mac_xmit();
|
||||
smsc9220_enable_xmit();
|
||||
SMSC9220->RX_CFG = 0;
|
||||
smsc9220_enable_mac_recv();
|
||||
|
||||
/* Rx status FIFO level irq threshold */
|
||||
SMSC9220->FIFO_INT &= ~(0xFF); /* Clear 2 bottom nibbles */
|
||||
|
||||
/* This sleep is compulsory otherwise txmit/receive will fail. */
|
||||
wait_ms(2000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void smsc9220_enable_interrupt(enum smsc9220_interrupt_source source)
|
||||
{
|
||||
SMSC9220->INT_EN |= (1 << source);
|
||||
}
|
||||
|
||||
void smsc9220_disable_interrupt(enum smsc9220_interrupt_source source)
|
||||
{
|
||||
SMSC9220->INT_EN &= ~(1 << source);
|
||||
}
|
||||
|
||||
void smsc9220_clear_interrupt(enum smsc9220_interrupt_source source)
|
||||
{
|
||||
SMSC9220->INT_STS |= (1 << source);
|
||||
}
|
||||
|
||||
int smsc9220_get_interrupt(enum smsc9220_interrupt_source source)
|
||||
{
|
||||
return (SMSC9220->INT_STS & (1 << source));
|
||||
}
|
||||
|
||||
void smsc9220_establish_link(void)
|
||||
{
|
||||
unsigned int bcr = 0;
|
||||
unsigned int hw_cfg = 0;
|
||||
|
||||
smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr);
|
||||
bcr |= (1 << 12) | (1 << 9);
|
||||
smsc9220_phy_regwrite(SMSC9220_PHY_BCONTROL, bcr);
|
||||
smsc9220_phy_regread(SMSC9220_PHY_BCONTROL, &bcr);
|
||||
|
||||
hw_cfg = SMSC9220->HW_CFG;
|
||||
hw_cfg &= 0xF0000;
|
||||
hw_cfg |= (1 << 20);
|
||||
SMSC9220->HW_CFG = hw_cfg;
|
||||
}
|
||||
|
||||
int smsc9220_read_mac_address(char *mac)
|
||||
{
|
||||
unsigned int mac_low = 0;
|
||||
unsigned int mac_high = 0;
|
||||
|
||||
if( !mac ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read current mac address. */
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_ADDRH, &mac_high)) {
|
||||
return 1;
|
||||
}
|
||||
if (smsc9220_mac_regread(SMSC9220_MAC_ADDRL, &mac_low)) {
|
||||
return 1;
|
||||
}
|
||||
mac[0] = mac_low & 0xFF;
|
||||
mac[1] = (mac_low >> 8) & 0xFF;
|
||||
mac[2] = (mac_low >> 16) & 0xFF;
|
||||
mac[3] = (mac_low >> 24) & 0xFF;
|
||||
mac[4] = mac_high & 0xFF;
|
||||
mac[5] = (mac_high >> 8) & 0xFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int smsc9220_get_tx_data_fifo_size(void)
|
||||
{
|
||||
const unsigned int tx_status_fifo_size = 512; /* fixed allocation in bytes */
|
||||
unsigned int tx_fifo_size = SMSC9220->HW_CFG;
|
||||
tx_fifo_size = (( tx_fifo_size >> 16 ) & 0x0F) * 1024; /* size is set in kbytes */
|
||||
return (tx_fifo_size - tx_status_fifo_size);
|
||||
}
|
||||
|
||||
int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet,
|
||||
const char *data, unsigned int current_size)
|
||||
{
|
||||
static unsigned int ongoing_packet_length = 0; /* size in bytes of the packet is sending */
|
||||
static unsigned int ongoing_packet_length_sent = 0; /* size in bytes of the packet has been sent */
|
||||
int is_first_segment = 0; /* signing this is the first segment of the packet to be sent */
|
||||
int is_last_segment = 0; /* signing this is the last segment of the packet to be sent */
|
||||
unsigned int txcmd_a, txcmd_b = 0;
|
||||
unsigned int dwords_to_write = 0;
|
||||
unsigned int xmit_inf = 0;
|
||||
unsigned int tx_buffer_free_space = 0;
|
||||
unsigned int xmit_stat = 0;
|
||||
|
||||
if (!data) {
|
||||
return -1; /* Invalid input parameter */
|
||||
}
|
||||
|
||||
if (is_new_packet) {
|
||||
is_first_segment = 1;
|
||||
ongoing_packet_length = total_packet_length;
|
||||
ongoing_packet_length_sent = 0;
|
||||
} else if (ongoing_packet_length != total_packet_length ||
|
||||
ongoing_packet_length_sent >= total_packet_length) {
|
||||
return -1; /* Invalid input parameter */
|
||||
}
|
||||
|
||||
/* Would next chunk fit into buffer? */
|
||||
xmit_inf = SMSC9220->TX_FIFO_INF;
|
||||
tx_buffer_free_space = xmit_inf & 0xFFFF;
|
||||
if (current_size > tx_buffer_free_space) {
|
||||
return -1; /* Not enough space in FIFO */
|
||||
}
|
||||
if ((ongoing_packet_length_sent + current_size) == total_packet_length) {
|
||||
is_last_segment = 1;
|
||||
}
|
||||
|
||||
txcmd_a = 0;
|
||||
txcmd_b = 0;
|
||||
|
||||
txcmd_a |= (is_last_segment << 12) | (is_first_segment << 13); /* Last and first segments */
|
||||
txcmd_a |= current_size & 0x7FF; /* [10:0] contains length */
|
||||
|
||||
txcmd_b |= ((current_size & 0xFFFF) << 16); /* [31:16] contains length */
|
||||
txcmd_b |= current_size & 0x7FF; /* [10:0] also contains length */
|
||||
|
||||
SMSC9220->TX_DATA_PORT = txcmd_a;
|
||||
SMSC9220->TX_DATA_PORT = txcmd_b;
|
||||
dwords_to_write = (current_size + 3) >> 2;
|
||||
|
||||
/*
|
||||
* Copy to TX FIFO
|
||||
* The function to use depends on the alignment of the data pointer on a 32
|
||||
* bits boundary.
|
||||
*/
|
||||
if (((unsigned int)data % sizeof(uint32_t)) == 0) {
|
||||
/* Cast is safe because we know data is aligned */
|
||||
fill_tx_fifo_aligned((unsigned int *)data, dwords_to_write);
|
||||
} else {
|
||||
fill_tx_fifo_unaligned((uint8_t *)data, dwords_to_write);
|
||||
}
|
||||
|
||||
if (is_last_segment) {
|
||||
/* pop status port */
|
||||
/* for error check it should be checked "at a later time" according to data sheet */
|
||||
xmit_stat = SMSC9220->TX_STAT_PORT;
|
||||
(void)xmit_stat;
|
||||
}
|
||||
|
||||
ongoing_packet_length_sent += current_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int smsc9220_get_rxfifo_data_used_space(void)
|
||||
{
|
||||
unsigned int rxfifo_inf = SMSC9220->RX_FIFO_INF;
|
||||
return rxfifo_inf & 0xFFFF;
|
||||
}
|
||||
|
||||
unsigned int smsc9220_receive_by_chunks(char *data, unsigned int dlen)
|
||||
{
|
||||
static unsigned int current_packet_size_words = 0;
|
||||
unsigned int rxfifo_inf = 0;
|
||||
unsigned int rxfifo_stat = 0;
|
||||
unsigned int dlen_word = 0;
|
||||
unsigned int read_length_word = 0;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!data) {
|
||||
return 0; /* Invalid input parameter */
|
||||
}
|
||||
|
||||
if (current_packet_size_words == 0) {
|
||||
/* First the packet status word should be read, */
|
||||
/* which tells the size of the data, */
|
||||
/* after the data can be read in synchron. */
|
||||
rxfifo_inf = SMSC9220->RX_FIFO_INF;
|
||||
|
||||
if(rxfifo_inf & 0xFFFF) { /* If there's data */
|
||||
rxfifo_stat = SMSC9220->RX_STAT_PORT;
|
||||
if(rxfifo_stat != 0) { /* Fetch status of this packet */
|
||||
if(rxfifo_stat & (1 << 15)) {
|
||||
current_packet_size_words = 0; /* error */
|
||||
}
|
||||
else {
|
||||
/* Ethernet controller is padding to 32bit aligned data */
|
||||
current_packet_size_words = (((rxfifo_stat >> 16) & 0x3FFF) + 3) >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dlen_word = dlen / 4;
|
||||
read_length_word = (dlen_word < current_packet_size_words) ? dlen_word : current_packet_size_words;
|
||||
|
||||
for (i = 0; i < read_length_word; i++) {
|
||||
((unsigned int*)data)[i] = SMSC9220->RX_DATA_PORT;
|
||||
current_packet_size_words--;
|
||||
}
|
||||
return (current_packet_size_words * 4);
|
||||
}
|
||||
|
||||
unsigned int smsc9220_peek_next_packet_size(void)
|
||||
{
|
||||
unsigned int packet_size = 0;
|
||||
unsigned int rx_stat_peek = 0;
|
||||
|
||||
if(smsc9220_get_rxfifo_data_used_space()) {
|
||||
rx_stat_peek = SMSC9220->RX_STAT_PEEK;
|
||||
packet_size = ((rx_stat_peek >> 16) & 0x3FFF);
|
||||
}
|
||||
return (((packet_size + 3) >> 2) << 2);
|
||||
}
|
||||
|
|
@ -1,170 +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.
|
||||
*/
|
||||
|
||||
/* This file is the re-implementation of mps2_ethernet_api and Selftest's ETH_MPS2.
|
||||
* MPS2 Selftest:https://silver.arm.com/browse/VEI10 ->
|
||||
* \ISCM-1-0\AN491\software\Selftest\v2m_mps2\
|
||||
*/
|
||||
#ifndef _SMSC9220_ETH_H_
|
||||
#define _SMSC9220_ETH_H_
|
||||
|
||||
enum smsc9220_interrupt_source {
|
||||
enum_smsc9220_interrupt_gpio0 = 0,
|
||||
enum_smsc9220_interrupt_gpio1 = 1,
|
||||
enum_smsc9220_interrupt_gpio2 = 2,
|
||||
enum_smsc9220_interrupt_rxstatus_fifo_level = 3,
|
||||
enum_smsc9220_interrupt_rxstatus_fifo_full = 4,
|
||||
/* 5 Reserved according to Datasheet */
|
||||
enum_smsc9220_interrupt_rx_dropped_frame = 6,
|
||||
enum_smsc9220_interrupt_txstatus_fifo_level = 7,
|
||||
enum_smsc9220_interrupt_txstatus_fifo_full = 8,
|
||||
enum_smsc9220_interrupt_txdata_fifo_available = 9,
|
||||
enum_smsc9220_interrupt_txdata_fifo_overrun = 10,
|
||||
/* 11, 12 Reserved according to Datasheet */
|
||||
enum_smsc9220_interrupt_transmit_error = 13,
|
||||
enum_smsc9220_interrupt_receive_error = 14,
|
||||
enum_smsc9220_interrupt_receive_watchdog_timeout = 15,
|
||||
enum_smsc9220_interrupt_txstatus_overflow = 16,
|
||||
enum_smsc9220_interrupt_power_management = 17,
|
||||
enum_smsc9220_interrupt_phy = 18,
|
||||
enum_smsc9220_interrupt_gp_timer = 19,
|
||||
enum_smsc9220_interrupt_rx_dma = 20,
|
||||
enum_smsc9220_interrupt_tx_ioc = 21,
|
||||
/* 22 Reserved according to Datasheet*/
|
||||
enum_smsc9220_interrupt_rx_dropped_frame_half = 23,
|
||||
enum_smsc9220_interrupt_rx_stopped = 24,
|
||||
enum_smsc9220_interrupt_tx_stopped = 25,
|
||||
/* 26 - 30 Reserved according to Datasheet*/
|
||||
enum_smsc9220_interrupt_sw = 31
|
||||
};
|
||||
|
||||
/* Function declarations */
|
||||
|
||||
/**
|
||||
* \brief Initialize SMS9220 Ethernet controller
|
||||
*
|
||||
* \return 0 if init is successful, 1 otherwise
|
||||
*/
|
||||
int smsc9220_init(void);
|
||||
|
||||
/**
|
||||
* \brief Enable the given interrupt source.
|
||||
*
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_enable_interrupt(enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Disable the given interrupt source.
|
||||
*
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_disable_interrupt(enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Clear the given interrupt source.
|
||||
*
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_clear_interrupt(enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Get the status of the given interrupt source.
|
||||
*
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*
|
||||
* \return non-zero if the given interrupt source is triggered, zero otherwise
|
||||
*/
|
||||
int smsc9220_get_interrupt(enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Establish link
|
||||
*/
|
||||
void smsc9220_establish_link(void);
|
||||
|
||||
/**
|
||||
* \brief Read MAC address from EEPROM.
|
||||
*
|
||||
* \param[in,out] mac array will include the read MAC address in
|
||||
* 6 bytes hexadecimal format.
|
||||
* It should be allocated by the caller to 6 bytes.
|
||||
*
|
||||
* \return 0 if read is successful, 1 otherwise
|
||||
*/
|
||||
int smsc9220_read_mac_address(char *mac);
|
||||
|
||||
/**
|
||||
* \brief Get the data size of the Tx buffer, aka Maximum Transition Unit
|
||||
*
|
||||
* \return Fifo data size in bytes
|
||||
*/
|
||||
unsigned int smsc9220_get_tx_data_fifo_size(void);
|
||||
|
||||
/**
|
||||
* \brief Send Ethernet packet from buffer chain.
|
||||
* The full packet length should be known in the beginning
|
||||
* of a new packet.
|
||||
*
|
||||
* \param[in] total_packet_length Length of the packet. Should be equal to
|
||||
* the sum of passed buffers within a packet.
|
||||
* \param[in] is_new_packet Should be set to non-zero if the passed buffer
|
||||
* should be sent as the start of a new packet.
|
||||
* If the current buffer should be sent as a full packet,
|
||||
* it should be set to non-zero respectively.
|
||||
* \param[in] data Pointer to the data should be sent.
|
||||
* \param[in] current_size Size of the data in bytes.
|
||||
*
|
||||
* \return 0 if the send process is successful, standard C error code otherwise
|
||||
*/
|
||||
int smsc9220_send_by_chunks(unsigned int total_packet_length, int is_new_packet,
|
||||
const char *data, unsigned int current_size);
|
||||
|
||||
/**
|
||||
* \brief Receive Ethernet packet from Rx FIFO to the passed buffer.
|
||||
* Stops reading at packet border.
|
||||
* If the passed buffer is larger than the current packet,
|
||||
* the whole packet will be read into the buffer.
|
||||
* If the current packet is larger than the passed buffer,
|
||||
* the buffer will be filled with data and the next call
|
||||
* will continue the read from that point.
|
||||
*
|
||||
* \param[in,out] data Pointer where the data will be read to.
|
||||
* The caller is responsible to allocate it.
|
||||
* \param[in] dlen Length of the allocated data in bytes.
|
||||
*
|
||||
* \return Remaining bytes left in the fifo of the current packet.
|
||||
*/
|
||||
unsigned int smsc9220_receive_by_chunks(char *data, unsigned int dlen);
|
||||
|
||||
/**
|
||||
* \brief Get the used space of Rx fifo in bytes.
|
||||
*
|
||||
* \return Data received and waiting for read in bytes
|
||||
*/
|
||||
unsigned int smsc9220_get_rxfifo_data_used_space(void);
|
||||
|
||||
/**
|
||||
* \brief Get the size of next unread packet in Rx buffer, using the peak
|
||||
* register, which is not destructive so can be read asynchronously.
|
||||
* Warning: In case of heavy receiving load, it's possible this register
|
||||
* is not perfectly in sync.
|
||||
*
|
||||
* \return Size in bytes of the next packet can be read from Rx fifo, according
|
||||
* to the peek register.
|
||||
*/
|
||||
unsigned int smsc9220_peek_next_packet_size(void);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,548 @@
|
|||
/*
|
||||
* Copyright (c) 2016-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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file smsc9220_drv.h
|
||||
* \brief Generic driver for SMSC9220 Ethernet controller
|
||||
*/
|
||||
|
||||
#ifndef __SMSC9220_ETH_H__
|
||||
#define __SMSC9220_ETH_H__
|
||||
|
||||
#include "stdbool.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** SMSC9220 device configuration structure */
|
||||
struct smsc9220_eth_dev_cfg_t {
|
||||
const uint32_t base; /*!< SMSC9220 base address */
|
||||
};
|
||||
|
||||
/** SMSC9220 device data structure */
|
||||
struct smsc9220_eth_dev_data_t {
|
||||
uint32_t state; /*!< Indicates if the SMSC9220 driver
|
||||
is initialized and enabled */
|
||||
void (*wait_ms) (int);/*!< function pointer to system's millisec delay
|
||||
function, will be used for delays */
|
||||
uint32_t ongoing_packet_length;/*!< size in bytes of the packet
|
||||
is being sent */
|
||||
uint32_t ongoing_packet_length_sent; /*!< size in bytes of the packet
|
||||
has been sent */
|
||||
uint32_t current_rx_size_words; /*!< Data length in words,
|
||||
currently is being read */
|
||||
};
|
||||
|
||||
/** SMSC9220 device structure */
|
||||
struct smsc9220_eth_dev_t {
|
||||
const struct smsc9220_eth_dev_cfg_t* const cfg; /*!< configuration */
|
||||
struct smsc9220_eth_dev_data_t* const data; /*!< data */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Error code definitions
|
||||
*
|
||||
*/
|
||||
enum smsc9220_error_t{
|
||||
SMSC9220_ERROR_NONE = 0U, /*!< no error */
|
||||
SMSC9220_ERROR_TIMEOUT = 1U, /*!< timeout */
|
||||
SMSC9220_ERROR_BUSY = 2U, /*!< no error */
|
||||
SMSC9220_ERROR_PARAM = 3U, /*!< invalid parameter */
|
||||
SMSC9220_ERROR_INTERNAL = 4U /*!< internal error */
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Interrupt source definitions
|
||||
*
|
||||
*/
|
||||
enum smsc9220_interrupt_source {
|
||||
SMSC9220_INTERRUPT_GPIO0 = 0U,
|
||||
SMSC9220_INTERRUPT_GPIO1 = 1U,
|
||||
SMSC9220_INTERRUPT_GPIO2 = 2U,
|
||||
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL = 3U,
|
||||
SMSC9220_INTERRUPT_RX_STATUS_FIFO_FULL = 4U,
|
||||
/* 5 Reserved according to Datasheet */
|
||||
SMSC9220_INTERRUPT_RX_DROPPED_FRAME = 6U,
|
||||
SMSC9220_INTERRUPT_TX_STATUS_FIFO_LEVEL = 7U,
|
||||
SMSC9220_INTERRUPT_TX_STATUS_FIFO_FULL = 8U,
|
||||
SMSC9220_INTERRUPT_TX_DATA_FIFO_AVAILABLE = 9U,
|
||||
SMSC9220_INTERRUPT_TX_DATA_FIFO_OVERRUN = 10U,
|
||||
/* 11, 12 Reserved according to Datasheet */
|
||||
SMSC9220_INTERRUPT_TX_ERROR = 13U,
|
||||
SMSC9220_INTERRUPT_RX_ERROR = 14U,
|
||||
SMSC9220_INTERRUPT_RX_WATCHDOG_TIMEOUT = 15U,
|
||||
SMSC9220_INTERRUPT_TX_STATUS_OVERFLOW = 16U,
|
||||
SMSC9220_INTERRUPT_TX_POWER_MANAGEMENT = 17U,
|
||||
SMSC9220_INTERRUPT_PHY = 18U,
|
||||
SMSC9220_INTERRUPT_GP_TIMER = 19U,
|
||||
SMSC9220_INTERRUPT_RX_DMA = 20U,
|
||||
SMSC9220_INTERRUPT_TX_IOC = 21U,
|
||||
/* 22 Reserved according to Datasheet*/
|
||||
SMSC9220_INTERRUPT_RX_DROPPED_FRAME_HALF = 23U,
|
||||
SMSC9220_INTERRUPT_RX_STOPPED = 24U,
|
||||
SMSC9220_INTERRUPT_TX_STOPPED = 25U,
|
||||
/* 26 - 30 Reserved according to Datasheet*/
|
||||
SMSC9220_INTERRUPT_SW = 31U
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief MAC register offset definitions
|
||||
*
|
||||
*/
|
||||
enum smsc9220_mac_reg_offsets_t{
|
||||
SMSC9220_MAC_REG_OFFSET_CR = 0x1U,
|
||||
SMSC9220_MAC_REG_OFFSET_ADDRH = 0x2U,
|
||||
SMSC9220_MAC_REG_OFFSET_ADDRL = 0x3U,
|
||||
SMSC9220_MAC_REG_OFFSET_HASHH = 0x4U,
|
||||
SMSC9220_MAC_REG_OFFSET_HASHL = 0x5U,
|
||||
SMSC9220_MAC_REG_OFFSET_MII_ACC = 0x6U,
|
||||
SMSC9220_MAC_REG_OFFSET_MII_DATA = 0x7U,
|
||||
SMSC9220_MAC_REG_OFFSET_FLOW = 0x8U,
|
||||
SMSC9220_MAC_REG_OFFSET_VLAN1 = 0x9U,
|
||||
SMSC9220_MAC_REG_OFFSET_VLAN2 = 0xAU,
|
||||
SMSC9220_MAC_REG_OFFSET_WUFF = 0xBU,
|
||||
SMSC9220_MAC_REG_OFFSET_WUCSR = 0xCU,
|
||||
SMSC9220_MAC_REG_OFFSET_COE_CR = 0xDU
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief PHY register offset definitions
|
||||
*
|
||||
*/
|
||||
enum phy_reg_offsets_t{
|
||||
SMSC9220_PHY_REG_OFFSET_BCTRL = 0x0U,
|
||||
SMSC9220_PHY_REG_OFFSET_BSTATUS = 0x1U,
|
||||
SMSC9220_PHY_REG_OFFSET_ID1 = 0x2U,
|
||||
SMSC9220_PHY_REG_OFFSET_ID2 = 0x3U,
|
||||
SMSC9220_PHY_REG_OFFSET_ANEG_ADV = 0x4U,
|
||||
SMSC9220_PHY_REG_OFFSET_ANEG_LPA = 0x5U,
|
||||
SMSC9220_PHY_REG_OFFSET_ANEG_EXP = 0x6U,
|
||||
SMSC9220_PHY_REG_OFFSET_MCONTROL = 0x17U,
|
||||
SMSC9220_PHY_REG_OFFSET_MSTATUS = 0x18U,
|
||||
SMSC9220_PHY_REG_OFFSET_CSINDICATE = 0x27U,
|
||||
SMSC9220_PHY_REG_OFFSET_INTSRC = 0x29U,
|
||||
SMSC9220_PHY_REG_OFFSET_INTMASK = 0x30U,
|
||||
SMSC9220_PHY_REG_OFFSET_CS = 0x31U
|
||||
};
|
||||
|
||||
/* Bit definitions for PHY Basic Status Register */
|
||||
#define PHY_REG_BSTATUS_EXTENDED_CAPABILITIES_INDEX 0U
|
||||
#define PHY_REG_BSTATUS_JABBER_DETECT_INDEX 1U
|
||||
#define PHY_REG_BSTATUS_LINK_STATUS_INDEX 2U
|
||||
#define PHY_REG_BSTATUS_AUTO_NEG_ABILITY_INDEX 3U
|
||||
#define PHY_REG_BSTATUS_REMOTE_FAULT_INDEX 4U
|
||||
#define PHY_REG_BSTATUS_AUTO_NEG_COMPLETE_INDEX 5U
|
||||
#define PHY_REG_BSTATUS_10BASE_T_HALF_DUPLEX_INDEX 11U
|
||||
#define PHY_REG_BSTATUS_10BASE_T_FULL_DUPLEX_INDEX 12U
|
||||
#define PHY_REG_BSTATUS_100BASE_TX_HALF_DUPLEX_INDEX 13U
|
||||
#define PHY_REG_BSTATUS_100BASE_TX_FULL_DUPLEX_INDEX 14U
|
||||
#define PHY_REG_BSTATUS_100BASE_T4_INDEX 15U
|
||||
|
||||
/**
|
||||
* \brief FIFO Level Interrupt bit definitions
|
||||
*
|
||||
*/
|
||||
enum smsc9220_fifo_level_irq_pos_t{
|
||||
SMSC9220_FIFO_LEVEL_IRQ_RX_STATUS_POS = 0U,
|
||||
SMSC9220_FIFO_LEVEL_IRQ_TX_STATUS_POS = 16U,
|
||||
SMSC9220_FIFO_LEVEL_IRQ_TX_DATA_POS = 24U
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief FIFO Level Interrupt limits
|
||||
*
|
||||
*/
|
||||
#define SMSC9220_FIFO_LEVEL_IRQ_MASK 0xFFU
|
||||
#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MIN 0U
|
||||
#define SMSC9220_FIFO_LEVEL_IRQ_LEVEL_MAX SMSC9220_FIFO_LEVEL_IRQ_MASK
|
||||
|
||||
/**
|
||||
* \brief Initializes SMSC9220 Ethernet controller to a known default state:
|
||||
* - device ID is checked
|
||||
* - global interrupt is enabled, but all irq sources are disabled
|
||||
* - all capabilities are advertised
|
||||
* - 10Mbps able
|
||||
* - 10Mbps with full duplex
|
||||
* - 100Mbps Tx able
|
||||
* - 100Mbps with full duplex
|
||||
* - Symmetric Pause
|
||||
* - Asymmetric Pause
|
||||
* - Establish link enabled
|
||||
* - Rx enabled
|
||||
* - Tx enabled
|
||||
* Init should be called prior to any other process and
|
||||
* it's the caller's responsibility to follow proper call order.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] wait_ms_function function pointer to a millisec delay function
|
||||
* for proper timing of some processes
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_init(const struct smsc9220_eth_dev_t* dev,
|
||||
void(* wait_ms_function)(int));
|
||||
|
||||
/**
|
||||
* \brief Read MAC register.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[in, out] data Pointer to register will be read
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_mac_regread(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_mac_reg_offsets_t regoffset,
|
||||
uint32_t *data);
|
||||
|
||||
/**
|
||||
* \brief Write MAC register.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[in] data Register value to write
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_mac_regwrite(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_mac_reg_offsets_t regoffset,
|
||||
uint32_t data);
|
||||
|
||||
/**
|
||||
* \brief Read PHY register.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[out] data Register value is read
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_phy_regread(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
enum phy_reg_offsets_t,
|
||||
uint32_t *data);
|
||||
|
||||
/**
|
||||
* \brief Write PHY register.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] regoffset Register offset
|
||||
* \param[in] data Register value to write
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_phy_regwrite(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
enum phy_reg_offsets_t,
|
||||
uint32_t data);
|
||||
|
||||
/**
|
||||
* \brief Read SMSC9220 ID.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return ID number
|
||||
*/
|
||||
uint32_t smsc9220_read_id(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Initiates a soft reset, returns failure or success.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_soft_reset(
|
||||
const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Set maximum transition unit by Tx fifo size.
|
||||
* Note: The MTU will be smaller by 512 bytes,
|
||||
* because the status uses this fixed space.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] val Size of the fifo in kbytes
|
||||
* \ref HW_CFG_REG_TX_FIFO_SIZE_MIN
|
||||
* \ref HW_CFG_REG_TX_FIFO_SIZE_MAX
|
||||
*/
|
||||
void smsc9220_set_txfifo(const struct smsc9220_eth_dev_t* dev,
|
||||
uint32_t val);
|
||||
|
||||
/**
|
||||
* \brief Set FIFO level interrupt for a given source
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] irq_level_pos Bit position of the FIFO to set
|
||||
* \ref smsc9220_fifo_level_irq_pos_t
|
||||
* \param[in] level Level of the FIFO, when the FIFO used space is greater
|
||||
* than this value, corresponding interrupt will be generated.
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_set_fifo_level_irq(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_fifo_level_irq_pos_t irq_level_pos,
|
||||
uint32_t level);
|
||||
|
||||
/**
|
||||
* \brief Wait for EEPROM to be ready to use.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_wait_eeprom(
|
||||
const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Initialise irqs by clearing and disabling all interrupt sources
|
||||
* and enable interrupts. Since all interrupt sources are disabled,
|
||||
* interrupt won't be triggered, until interrupt sources won't be
|
||||
* enabled by \ref smsc9220_enable_interrupt
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_init_irqs(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Check PHY ID registers.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_check_phy(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Reset PHY
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_reset_phy(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Advertise all speeds and pause capabilities
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_advertise_cap(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enable transmission
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_enable_xmit(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disable transmission
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_disable_xmit(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enable MAC transmitter
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_enable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disable MAC transmitter
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_disable_mac_xmit(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enable receive
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_enable_mac_recv(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Disable receive
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_disable_mac_recv(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Enable the given interrupt source.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_enable_interrupt(const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Disable the given interrupt source.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_disable_interrupt(const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Disable all of the interrupt sources.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_disable_all_interrupts(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Clear the given interrupt source.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*/
|
||||
void smsc9220_clear_interrupt(const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Clear all of the interrupt sources.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_clear_all_interrupts(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Get the status of the given interrupt source.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] source Enum of the interrupt source.
|
||||
*
|
||||
* \return non-zero if the given interrupt source is triggered, zero otherwise
|
||||
*/
|
||||
int smsc9220_get_interrupt(const struct smsc9220_eth_dev_t* dev,
|
||||
enum smsc9220_interrupt_source source);
|
||||
|
||||
/**
|
||||
* \brief Establish link
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*/
|
||||
void smsc9220_establish_link(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Read MAC address from EEPROM.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in,out] mac array will include the read MAC address in
|
||||
* 6 bytes hexadecimal format.
|
||||
* It should be allocated by the caller to 6 bytes.
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_read_mac_address(
|
||||
const struct smsc9220_eth_dev_t* dev, char *mac);
|
||||
|
||||
/**
|
||||
* \brief Check device ID.
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
int smsc9220_check_id(const struct smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Get the data size of the Tx buffer, aka Maximum Transition Unit
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return Fifo data size in bytes
|
||||
*/
|
||||
uint32_t smsc9220_get_tx_data_fifo_size(const struct
|
||||
smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Send Ethernet packet from buffer chain.
|
||||
* The full packet length should be known in the beginning
|
||||
* of a new packet.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in] total_payload_length Length of the ethernet payload.
|
||||
* Should be equal to the sum of passed buffers within a packet.
|
||||
* \param[in] is_new_packet Should be set to true if the input buffer has to
|
||||
* be sent as the start of a new packet or as a full packet.
|
||||
* \param[in] data Pointer to the data should be sent.
|
||||
* \param[in] current_size Size of the data in bytes.
|
||||
*
|
||||
* \return error code /ref smsc9220_error_t
|
||||
*/
|
||||
enum smsc9220_error_t smsc9220_send_by_chunks(
|
||||
const struct smsc9220_eth_dev_t* dev,
|
||||
uint32_t total_payload_length,
|
||||
bool is_new_packet,
|
||||
const char *data, uint32_t current_size);
|
||||
|
||||
/**
|
||||
* \brief Receive Ethernet packet from Rx FIFO to the passed buffer.
|
||||
* Stops reading at packet border.
|
||||
* If the passed buffer is larger than the current packet,
|
||||
* the whole packet will be read into the buffer.
|
||||
* If the current packet is larger than the passed buffer,
|
||||
* the buffer will be filled with data and the next call
|
||||
* will continue the read from that point.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
* \param[in,out] data Pointer where the data will be read to.
|
||||
* The caller is responsible to allocate it.
|
||||
* \param[in] dlen Length of the allocated data in bytes.
|
||||
*
|
||||
* \return Remaining bytes left in the fifo of the current packet.
|
||||
*/
|
||||
uint32_t smsc9220_receive_by_chunks(const struct smsc9220_eth_dev_t* dev,
|
||||
char *data, uint32_t dlen);
|
||||
|
||||
/**
|
||||
* \brief Get the used space of Rx fifo in bytes.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return Data received and waiting for read in bytes
|
||||
*/
|
||||
uint32_t smsc9220_get_rxfifo_data_used_space(const struct
|
||||
smsc9220_eth_dev_t* dev);
|
||||
|
||||
/**
|
||||
* \brief Get the size of next unread packet in Rx buffer, using the peak
|
||||
* register, which is not destructive so can be read asynchronously.
|
||||
* Warning: In case of heavy receiving load, it's possible this register
|
||||
* is not perfectly in sync.
|
||||
*
|
||||
* \param[in] dev Ethernet device structure \ref smsc9220_eth_dev_t
|
||||
*
|
||||
* \return Size in bytes of the next packet can be read from Rx fifo, according
|
||||
* to the peek register.
|
||||
*/
|
||||
uint32_t smsc9220_peek_next_packet_size(const struct
|
||||
smsc9220_eth_dev_t* dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SMSC9220_ETH_H__ */
|
|
@ -270,3 +270,13 @@ static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = {
|
|||
struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG),
|
||||
&(ARM_UART4_DEV_DATA)};
|
||||
#endif /* ARM_UART4 */
|
||||
|
||||
/* SMSC9220 Ethernet driver structures */
|
||||
#ifdef SMSC9220_ETH
|
||||
static const struct smsc9220_eth_dev_cfg_t SMSC9220_ETH_DEV_CFG = {
|
||||
.base = SMSC9220_BASE};
|
||||
static struct smsc9220_eth_dev_data_t SMSC9220_ETH_DEV_DATA = {
|
||||
.state = 0};
|
||||
struct smsc9220_eth_dev_t SMSC9220_ETH_DEV = {&(SMSC9220_ETH_DEV_CFG),
|
||||
&(SMSC9220_ETH_DEV_DATA)};
|
||||
#endif
|
|
@ -26,6 +26,7 @@
|
|||
#include "arm_mps2_io_drv.h"
|
||||
#include "spi_pl022_drv.h"
|
||||
#include "arm_uart_drv.h"
|
||||
#include "smsc9220_eth_drv.h"
|
||||
|
||||
/* ======= Defines peripheral configuration structures ======= */
|
||||
|
||||
|
@ -96,4 +97,8 @@ extern struct arm_uart_dev_t ARM_UART3_DEV;
|
|||
extern struct arm_uart_dev_t ARM_UART4_DEV;
|
||||
#endif
|
||||
|
||||
#ifdef SMSC9220_ETH
|
||||
extern struct smsc9220_eth_dev_t SMSC9220_ETH_DEV;
|
||||
#endif
|
||||
|
||||
#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-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 <string.h>
|
||||
|
||||
#include "ethernet_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "mbed_interface.h"
|
||||
#include "mbed_toolchain.h"
|
||||
#include "mbed_error.h"
|
||||
#include "mbed_wait_api.h"
|
||||
#include "smsc9220_eth.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Ethernet Device initialize
|
||||
*----------------------------------------------------------------------------*/
|
||||
int ethernet_init()
|
||||
{
|
||||
return smsc9220_init();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Ethernet Device Uninitialize
|
||||
*----------------------------------------------------------------------------*/
|
||||
void ethernet_free()
|
||||
{
|
||||
/* Uninitialize function is not implemented in Ethernet driver. */
|
||||
}
|
||||
|
||||
int ethernet_write(const char *data, int size)
|
||||
{
|
||||
/* smsc9220 cannot provide the functionality of writing into the tx buffer */
|
||||
/* by chunks, without knowing the full size of the packet in the beginning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ethernet_send()
|
||||
{
|
||||
/* smsc9220 cannot provide the functionality of writing into the tx buffer */
|
||||
/* by chunks, without knowing the full size of the packet in the beginning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ethernet_receive()
|
||||
{
|
||||
return smsc9220_peek_next_packet_size();
|
||||
}
|
||||
|
||||
/* Read from an recevied ethernet packet.*/
|
||||
/* After receive returnd a number bigger than 0 it is*/
|
||||
/* possible to read bytes from this packet.*/
|
||||
/* Read will write up to size bytes into data.*/
|
||||
/* It is possible to use read multible times.*/
|
||||
/* Each time read will start reading after the last read byte before. */
|
||||
int ethernet_read(char *data, int dlen)
|
||||
{
|
||||
return smsc9220_receive_by_chunks(data, dlen);
|
||||
}
|
||||
|
||||
void ethernet_address(char *mac)
|
||||
{
|
||||
smsc9220_read_mac_address(mac);
|
||||
}
|
||||
|
||||
int ethernet_link(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ethernet_set_link(int speed, int duplex)
|
||||
{
|
||||
smsc9220_establish_link();
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* mbed Microcontroller Library
|
||||
|
||||
* Copyright (c) 2006-2017 ARM Limited
|
||||
* Copyright (c) 2006-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.
|
||||
|
@ -15,10 +15,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "smsc9220_eth.h"
|
||||
#include "platform_devices.h"
|
||||
#include "smsc9220_eth_drv.h"
|
||||
|
||||
/* Provide ethernet devices with a semi-unique MAC address from the UUID */
|
||||
void mbed_mac_address(char *mac)
|
||||
{
|
||||
smsc9220_read_mac_address(mac);
|
||||
smsc9220_read_mac_address(&SMSC9220_ETH_DEV, mac);
|
||||
}
|
||||
|
||||
|
|
|
@ -2929,13 +2929,17 @@
|
|||
"inherits": ["ARM_IOTSS_Target"],
|
||||
"core": "Cortex-M3",
|
||||
"supported_toolchains": ["ARM", "GCC_ARM", "IAR"],
|
||||
"components": ["SMSC9220"],
|
||||
"extra_labels": ["ARM_SSG", "CM3DS_MPS2"],
|
||||
"OUTPUT_EXT": "elf",
|
||||
"macros": ["CMSDK_CM3DS"],
|
||||
"device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "TRNG", "FLASH"],
|
||||
"device_has": ["ANALOGIN", "EMAC", "FLASH", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "TRNG"],
|
||||
"release_versions": ["2", "5"],
|
||||
"copy_method": "mps2",
|
||||
"reset_method": "reboot.txt"
|
||||
"reset_method": "reboot.txt",
|
||||
"overrides": {
|
||||
"target.network-default-interface-type": "ETHERNET"
|
||||
}
|
||||
},
|
||||
"ARM_BEETLE_SOC": {
|
||||
"inherits": ["ARM_IOTSS_Target"],
|
||||
|
|
Loading…
Reference in New Issue