fix network driver:add select,ioctl;expand TCP packet length

fix/double
jiangxiangbing 2019-02-27 18:09:54 +08:00
parent e5fbb28a9d
commit 863d783ea0
19 changed files with 468 additions and 207 deletions

View File

@ -292,6 +292,7 @@ double k_spi_driver::set_clock_rate(k_spi_device_driver &device, double clock_ra
int k_spi_driver::read(k_spi_device_driver &device, gsl::span<uint8_t> buffer) int k_spi_driver::read(k_spi_device_driver &device, gsl::span<uint8_t> buffer)
{ {
COMMON_ENTRY; COMMON_ENTRY;
setup_device(device); setup_device(device);
uint32_t i = 0; uint32_t i = 0;
@ -308,6 +309,7 @@ int k_spi_driver::read(k_spi_device_driver &device, gsl::span<uint8_t> buffer)
if (rx_frames < SPI_TRANSMISSION_THRESHOLD) if (rx_frames < SPI_TRANSMISSION_THRESHOLD)
{ {
vTaskEnterCritical();
size_t index, fifo_len; size_t index, fifo_len;
while (rx_frames) while (rx_frames)
{ {
@ -335,6 +337,7 @@ int k_spi_driver::read(k_spi_device_driver &device, gsl::span<uint8_t> buffer)
} }
rx_frames -= fifo_len; rx_frames -= fifo_len;
} }
vTaskExitCritical();
} }
else else
{ {
@ -355,12 +358,14 @@ int k_spi_driver::read(k_spi_device_driver &device, gsl::span<uint8_t> buffer)
spi_.ser = 0x00; spi_.ser = 0x00;
spi_.ssienr = 0x00; spi_.ssienr = 0x00;
spi_.dmacr = 0x00; spi_.dmacr = 0x00;
return buffer.size(); return buffer.size();
} }
int k_spi_driver::write(k_spi_device_driver &device, gsl::span<const uint8_t> buffer) int k_spi_driver::write(k_spi_device_driver &device, gsl::span<const uint8_t> buffer)
{ {
COMMON_ENTRY; COMMON_ENTRY;
setup_device(device); setup_device(device);
uint32_t i = 0; uint32_t i = 0;
@ -371,6 +376,7 @@ int k_spi_driver::write(k_spi_device_driver &device, gsl::span<const uint8_t> bu
if (tx_frames < SPI_TRANSMISSION_THRESHOLD) if (tx_frames < SPI_TRANSMISSION_THRESHOLD)
{ {
vTaskEnterCritical();
size_t index, fifo_len; size_t index, fifo_len;
spi_.ssienr = 0x01; spi_.ssienr = 0x01;
write_inst_addr(spi_.dr, &buffer_write, device.inst_width_); write_inst_addr(spi_.dr, &buffer_write, device.inst_width_);
@ -399,6 +405,7 @@ int k_spi_driver::write(k_spi_device_driver &device, gsl::span<const uint8_t> bu
} }
tx_buffer_len -= fifo_len; tx_buffer_len -= fifo_len;
} }
vTaskExitCritical();
} }
else else
{ {
@ -420,6 +427,7 @@ int k_spi_driver::write(k_spi_device_driver &device, gsl::span<const uint8_t> bu
spi_.ser = 0x00; spi_.ser = 0x00;
spi_.ssienr = 0x00; spi_.ssienr = 0x00;
spi_.dmacr = 0x00; spi_.dmacr = 0x00;
return buffer.size(); return buffer.size();
} }
@ -452,6 +460,7 @@ int k_spi_driver::read_write(k_spi_device_driver &device, gsl::span<const uint8_
if (rx_frames < SPI_TRANSMISSION_THRESHOLD) if (rx_frames < SPI_TRANSMISSION_THRESHOLD)
{ {
vTaskEnterCritical();
size_t index, fifo_len; size_t index, fifo_len;
spi_.ctrlr1 = rx_frames - 1; spi_.ctrlr1 = rx_frames - 1;
spi_.ssienr = 0x01; spi_.ssienr = 0x01;
@ -504,6 +513,7 @@ int k_spi_driver::read_write(k_spi_device_driver &device, gsl::span<const uint8_
spi_.ser = device.chip_select_mask_; spi_.ser = device.chip_select_mask_;
rx_buffer_len -= fifo_len; rx_buffer_len -= fifo_len;
} }
vTaskExitCritical();
} }
else else
{ {

View File

@ -312,8 +312,8 @@ public:
} }
/************************************************ /************************************************
*** Activate DM9051 and Setup DM9051 Registers ** *** Activate DM9051 and Setup DM9051 Registers **
*************************************************/ *************************************************/
/* Clear DM9051 Set and Disable Wakeup function */ /* Clear DM9051 Set and Disable Wakeup function */
write(DM9051_NCR, NCR_DEFAULT); write(DM9051_NCR, NCR_DEFAULT);
/* Clear TCR Register set */ /* Clear TCR Register set */
@ -348,8 +348,9 @@ public:
{ {
configASSERT(length <= std::numeric_limits<uint16_t>::max()); configASSERT(length <= std::numeric_limits<uint16_t>::max());
while (read(DM9051_TCR) & DM9051_TCR_SET) while (read(DM9051_TCR) & DM9051_TCR_SET)
; {
usleep(5000);
}
write(DM9051_TXPLL, length & 0xff); write(DM9051_TXPLL, length & 0xff);
write(DM9051_TXPLH, (length >> 8) & 0xff); write(DM9051_TXPLH, (length >> 8) & 0xff);
} }
@ -370,12 +371,12 @@ public:
uint16_t len = 0; uint16_t len = 0;
uint16_t status; uint16_t status;
read(DM9051_MRCMDX); // dummy read read(DM9051_MRCMDX); // dummy read
uint8_t header[4]; uint8_t header[4];
read_memory({ header }); read_memory({ header });
status = header[0] | (header[1] << 8); status = header[0] | (header[1] << 8);
len = header[2] | (header[3] << 8); len = header[2] | (header[3] << 8);
if (len > DM9051_PKT_MAX) if (len > DM9051_PKT_MAX)
{ // read-error { // read-error
len = 0; // read-error (keep no change to rx fifo) len = 0; // read-error (keep no change to rx fifo)
@ -455,14 +456,14 @@ private:
xSemaphoreGiveFromISR(driver.interrupt_event_, &xHigherPriorityTaskWoken); xSemaphoreGiveFromISR(driver.interrupt_event_, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) if (xHigherPriorityTaskWoken)
{ {
portYIELD(); portYIELD_FROM_ISR();
} }
} }
uint8_t read(uint8_t addr) uint8_t read(uint8_t addr)
{ {
const uint8_t to_write[1] = { addr }; const uint8_t to_write[1] = { addr };
uint8_t to_read[1]; uint8_t to_read[1] = { 0 };
spi_dev_->transfer_sequential({ to_write }, { to_read }); spi_dev_->transfer_sequential({ to_write }, { to_read });
return to_read[0]; return to_read[0];
} }

View File

@ -68,7 +68,7 @@
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
#define configMAX_PRIORITIES ( 5 ) #define configMAX_PRIORITIES ( 5 )
#define configMAX_TASK_NAME_LEN ( 16 ) #define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0 #define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0 #define configIDLE_SHOULD_YIELD 0
#define configQUEUE_REGISTRY_SIZE 8 #define configQUEUE_REGISTRY_SIZE 8

View File

@ -54,12 +54,15 @@ void handle_irq_m_soft(uintptr_t *regs, uintptr_t cause)
void core_sync_request(uint64_t core_id, int event) void core_sync_request(uint64_t core_id, int event)
{ {
vTaskEnterCritical();
corelock_lock(&s_core_sync_locks[core_id]); corelock_lock(&s_core_sync_locks[core_id]);
while (s_core_sync_events[core_id] != CORE_SYNC_NONE) while (s_core_sync_events[core_id] != CORE_SYNC_NONE)
; ;
s_core_sync_events[core_id] = event; s_core_sync_events[core_id] = event;
clint_ipi_send(core_id); clint_ipi_send(core_id);
corelock_unlock(&s_core_sync_locks[core_id]); corelock_unlock(&s_core_sync_locks[core_id]);
vTaskExitCritical();
} }
void core_sync_complete(uint64_t core_id) void core_sync_complete(uint64_t core_id)

View File

@ -60,6 +60,23 @@ MAKE_ENUM_CLASS_BITMASK_TYPE(file_access_t);
MAKE_ENUM_CLASS_BITMASK_TYPE(file_mode_t); MAKE_ENUM_CLASS_BITMASK_TYPE(file_mode_t);
MAKE_ENUM_CLASS_BITMASK_TYPE(socket_message_flag_t); MAKE_ENUM_CLASS_BITMASK_TYPE(socket_message_flag_t);
class errno_exception : public std::runtime_error
{
public:
explicit errno_exception(const char *msg, int code) noexcept
: runtime_error(msg), code_(code)
{
}
int code() const noexcept
{
return code_;
}
private:
int code_;
};
class object_access : public virtual object class object_access : public virtual object
{ {
public: public:
@ -410,7 +427,7 @@ public:
virtual void end_receive() = 0; virtual void end_receive() = 0;
}; };
class network_socket : public virtual object_access class network_socket : public virtual custom_driver, public virtual object_access
{ {
public: public:
virtual object_accessor<network_socket> accept(socket_address_t *remote_address) = 0; virtual object_accessor<network_socket> accept(socket_address_t *remote_address) = 0;
@ -424,6 +441,8 @@ public:
virtual size_t receive_from(gsl::span<uint8_t> buffer, socket_message_flag_t flags, socket_address_t *from) = 0; virtual size_t receive_from(gsl::span<uint8_t> buffer, socket_message_flag_t flags, socket_address_t *from) = 0;
virtual size_t read(gsl::span<uint8_t> buffer) = 0; virtual size_t read(gsl::span<uint8_t> buffer) = 0;
virtual size_t write(gsl::span<const uint8_t> buffer) = 0; virtual size_t write(gsl::span<const uint8_t> buffer) = 0;
virtual int fcntl(int cmd, int val) = 0;
virtual void select(fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) = 0;
}; };
extern driver_registry_t g_hal_drivers[]; extern driver_registry_t g_hal_drivers[];

View File

@ -257,6 +257,8 @@ int network_socket_send_to(handle_t socket_handle, const uint8_t *data, size_t l
* - other Fail * - other Fail
*/ */
int network_socket_receive_from(handle_t socket_handle, uint8_t *data, size_t len, socket_message_flag_t flags, socket_address_t *from); int network_socket_receive_from(handle_t socket_handle, uint8_t *data, size_t len, socket_message_flag_t flags, socket_address_t *from);
int network_socket_fcntl(handle_t socket_handle, int cmd, int val);
int network_socket_select(handle_t socket_handle, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout);
/** /**
* @brief Get host address information by name * @brief Get host address information by name

View File

@ -335,6 +335,19 @@ typedef enum _dhcp_state
DHCP_FAIL DHCP_FAIL
} dhcp_state_t; } dhcp_state_t;
#define SYS_IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */
#define SYS_IOC_VOID 0x20000000UL /* no parameters */
#define SYS_IOC_OUT 0x40000000UL /* copy out parameters */
#define SYS_IOC_IN 0x80000000UL /* copy in parameters */
#define SYS_IOC_INOUT (SYS_IOC_IN | SYS_IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */
#define SYS_IO(x, y) (SYS_IOC_VOID | ((x) << 8) | (y))
#define SYS_IOR(x, y, t) (SYS_IOC_OUT | (((uint32_t)sizeof(t) & SYS_IOCPARM_MASK) << 16) | ((x) << 8) | (y))
#define SYS_IOW(x, y, t) (SYS_IOC_IN | (((uint32_t)sizeof(t) & SYS_IOCPARM_MASK) << 16) | ((x) << 8) | (y))
#define SYS_FIONBIO SYS_IOW('f', 126, uint32_t) /* set/clear non-blocking i/o */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -45,6 +45,13 @@ using namespace sys;
} \ } \
} }
#define CATCH_ALL \
catch (errno_exception & e) \
{ \
errno = e.code(); \
return -1; \
}
typedef struct typedef struct
{ {
object_accessor<object_access> object; object_accessor<object_access> object;
@ -192,19 +199,23 @@ static void dma_add_free();
int io_read(handle_t file, uint8_t *buffer, size_t len) int io_read(handle_t file, uint8_t *buffer, size_t len)
{ {
configASSERT(file >= HANDLE_OFFSET); try
_file *rfile = (_file *)handles_[file - HANDLE_OFFSET];
/* clang-format off */
DEFINE_READ_PROXY(uart_driver)
else DEFINE_READ_PROXY(i2c_device_driver)
else DEFINE_READ_PROXY(spi_device_driver)
else DEFINE_READ_PROXY(filesystem_file)
else DEFINE_READ_PROXY(network_socket)
else
{ {
return -1; configASSERT(file >= HANDLE_OFFSET);
_file *rfile = (_file *)handles_[file - HANDLE_OFFSET];
/* clang-format off */
DEFINE_READ_PROXY(uart_driver)
else DEFINE_READ_PROXY(i2c_device_driver)
else DEFINE_READ_PROXY(spi_device_driver)
else DEFINE_READ_PROXY(filesystem_file)
else DEFINE_READ_PROXY(network_socket)
else
{
return -1;
}
/* clang-format on */
} }
/* clang-format on */ CATCH_ALL;
} }
static void io_free(_file *file) static void io_free(_file *file)
@ -273,27 +284,39 @@ int io_close(handle_t file)
int io_write(handle_t file, const uint8_t *buffer, size_t len) int io_write(handle_t file, const uint8_t *buffer, size_t len)
{ {
configASSERT(file >= HANDLE_OFFSET); try
_file *rfile = (_file *)handles_[file - HANDLE_OFFSET];
/* clang-format off */
DEFINE_WRITE_PROXY(uart_driver)
else DEFINE_WRITE_PROXY(i2c_device_driver)
else DEFINE_WRITE_PROXY(spi_device_driver)
else DEFINE_WRITE_PROXY(filesystem_file)
else DEFINE_WRITE_PROXY(network_socket)
else
{ {
return -1; configASSERT(file >= HANDLE_OFFSET);
_file *rfile = (_file *)handles_[file - HANDLE_OFFSET];
/* clang-format off */
DEFINE_WRITE_PROXY(uart_driver)
else DEFINE_WRITE_PROXY(i2c_device_driver)
else DEFINE_WRITE_PROXY(spi_device_driver)
else DEFINE_WRITE_PROXY(filesystem_file)
else DEFINE_WRITE_PROXY(network_socket)
else
{
return -1;
}
/* clang-format on */
} }
/* clang-format on */ CATCH_ALL;
} }
int io_control(handle_t file, uint32_t control_code, const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len) int io_control(handle_t file, uint32_t control_code, const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len)
{ {
_file *rfile = (_file *)handles_[file - HANDLE_OFFSET]; try
DEFINE_CONTROL_PROXY(custom) {
configASSERT(file >= HANDLE_OFFSET);
return -1; _file *rfile = (_file *)handles_[file - HANDLE_OFFSET];
DEFINE_CONTROL_PROXY(custom)
else
{
return -1;
}
}
CATCH_ALL;
} }
/* Device IO Implementation Helper Macros */ /* Device IO Implementation Helper Macros */

View File

@ -13,6 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
#include "network.h" #include "network.h"
#include "semphr.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "devices.h" #include "devices.h"
#include "kernel/driver_impl.hpp" #include "kernel/driver_impl.hpp"
@ -26,9 +27,11 @@
#include <lwip/netdb.h> #include <lwip/netdb.h>
#include <netif/ethernet.h> #include <netif/ethernet.h>
#include <string.h> #include <string.h>
using namespace sys; using namespace sys;
#define MAX_DHCP_TRIES 5 #define MAX_DHCP_TRIES 5
#define NETIF_GUARD_BLOCK_TIME (250 )
int network_init() int network_init()
{ {
@ -43,7 +46,7 @@ public:
: adapter_(std::move(adapter)) : adapter_(std::move(adapter))
{ {
ip4_addr_t ipaddr, netmask, gw; ip4_addr_t ipaddr, netmask, gw;
completion_event_ = xSemaphoreCreateCounting(20, 0); completion_event_ = xSemaphoreCreateBinary();
IP4_ADDR(&ipaddr, ip_address.data[0], ip_address.data[1], ip_address.data[2], ip_address.data[3]); IP4_ADDR(&ipaddr, ip_address.data[0], ip_address.data[1], ip_address.data[2], ip_address.data[3]);
IP4_ADDR(&netmask, net_mask.data[0], net_mask.data[1], net_mask.data[2], net_mask.data[3]); IP4_ADDR(&netmask, net_mask.data[0], net_mask.data[1], net_mask.data[2], net_mask.data[3]);
@ -60,7 +63,7 @@ public:
netif_set_up(&netif_); netif_set_up(&netif_);
TaskHandle_t h; TaskHandle_t h;
auto ret = xTaskCreate(poll_thread, "poll", 10240, this, 3, &h); auto ret = xTaskCreate(poll_thread, "poll", 4096*8, this, 3, &h);
configASSERT(ret == pdTRUE); configASSERT(ret == pdTRUE);
} }
else else
@ -206,7 +209,7 @@ private:
static void ethernetif_input(struct netif *netif) static void ethernetif_input(struct netif *netif)
{ {
struct pbuf *p; struct pbuf *p = NULL;
/* move received packet into a new pbuf */ /* move received packet into a new pbuf */
p = low_level_input(netif); p = low_level_input(netif);
@ -249,10 +252,10 @@ private:
#if LWIP_IPV6 && LWIP_IPV6_MLD #if LWIP_IPV6 && LWIP_IPV6_MLD
/* /*
* For hardware/netifs that implement MAC filtering. * For hardware/netifs that implement MAC filtering.
* All-nodes link-local is handled by default, so we must let the hardware know * All-nodes link-local is handled by default, so we must let the hardware know
* to allow multicast packets in. * to allow multicast packets in.
* Should set mld_mac_filter previously. */ * Should set mld_mac_filter previously. */
if (netif->mld_mac_filter != NULL) if (netif->mld_mac_filter != NULL)
{ {
ip6_addr_t ip6_allnodes_ll; ip6_addr_t ip6_allnodes_ll;
@ -267,115 +270,135 @@ private:
static struct pbuf *low_level_input(struct netif *netif) static struct pbuf *low_level_input(struct netif *netif)
{ {
static xSemaphoreHandle xRxSemaphore = NULL;
auto &ethnetif = *reinterpret_cast<k_ethernet_interface *>(netif->state); auto &ethnetif = *reinterpret_cast<k_ethernet_interface *>(netif->state);
auto &adapter = ethnetif.adapter_; auto &adapter = ethnetif.adapter_;
struct pbuf *p, *q; struct pbuf *p = NULL, *q = NULL;
u16_t len; u16_t len;
if (xRxSemaphore == NULL)
/* Obtain the size of the packet and put it into the "len" variable. */
len = adapter->begin_receive();
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL)
{ {
vSemaphoreCreateBinary (xRxSemaphore);
}
#if ETH_PAD_SIZE if (xSemaphoreTake(xRxSemaphore, NETIF_GUARD_BLOCK_TIME))
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */ {
#endif /* Obtain the size of the packet and put it into the "len" variable. */
len = adapter->begin_receive();
/* We iterate over the pbuf chain until we have read the entire #if ETH_PAD_SIZE
* packet into the pbuf. */ len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
for (q = p; q != NULL; q = q->next) #endif
/* We allocate a pbuf chain of pbufs from the pool. */
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL)
{ {
/* 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.
*/
adapter->receive({ (uint8_t *)q->payload, q->len });
}
adapter->end_receive(); #if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
#endif
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len); /* We iterate over the pbuf chain until we have read the entire
if (((u8_t *)p->payload)[0] & 1) * packet into the pbuf. */
{ for (q = p; q != NULL; q = q->next)
/* broadcast or multicast packet*/ {
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts); /* 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.
*/
adapter->receive({ (uint8_t *)q->payload, q->len });
}
adapter->end_receive();
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet*/
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
}
else
{
/* unicast packet*/
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
}
#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} }
else else
{ {
/* unicast packet*/ adapter->end_receive();
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
} }
#if ETH_PAD_SIZE xSemaphoreGive(xRxSemaphore);
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} }
else
{
adapter->end_receive();
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
MIB2_STATS_NETIF_INC(netif, ifindiscards);
}
return p; return p;
} }
static err_t low_level_output(struct netif *netif, struct pbuf *p) static err_t low_level_output(struct netif *netif, struct pbuf *p)
{ {
static xSemaphoreHandle xTxSemaphore = NULL;
auto &ethnetif = *reinterpret_cast<k_ethernet_interface *>(netif->state); auto &ethnetif = *reinterpret_cast<k_ethernet_interface *>(netif->state);
auto &adapter = ethnetif.adapter_; auto &adapter = ethnetif.adapter_;
struct pbuf *q; struct pbuf *q;
adapter->begin_send(p->tot_len); if (xTxSemaphore == NULL)
#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
#endif
for (q = p; q != NULL; q = q->next)
{ {
/* Send the data from the pbuf to the interface, one pbuf at a xTxSemaphore = xSemaphoreCreateMutex();
time. The size of the data in each pbuf is kept in the ->len
variable. */
adapter->send({ (uint8_t *)q->payload, q->len });
} }
adapter->end_send(); if (xTxSemaphore != NULL)
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{ {
/* broadcast or multicast packet*/ if (xSemaphoreTake(xTxSemaphore, NETIF_GUARD_BLOCK_TIME))
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts); {
adapter->begin_send(p->tot_len);
#if ETH_PAD_SIZE
pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
#endif
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. */
adapter->send({ (uint8_t *)q->payload, q->len });
}
adapter->end_send();
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
if (((u8_t *)p->payload)[0] & 1)
{
/* broadcast or multicast packet*/
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
}
else
{
/* unicast packet */
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
}
/* increase ifoutdiscards or ifouterrors on error */
#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
xSemaphoreGive(xTxSemaphore);
}
} }
else
{
/* unicast packet */
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
}
/* increase ifoutdiscards or ifouterrors on error */
#if ETH_PAD_SIZE
pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK; return ERR_OK;
} }

View File

@ -17,6 +17,7 @@
#include "kernel/driver_impl.hpp" #include "kernel/driver_impl.hpp"
#include "network.h" #include "network.h"
#include <lwip/sockets.h> #include <lwip/sockets.h>
#include <lwip/errno.h>
#include <string.h> #include <string.h>
using namespace sys; using namespace sys;
@ -24,7 +25,9 @@ using namespace sys;
static void check_lwip_error(int result) static void check_lwip_error(int result)
{ {
if (result < 0) if (result < 0)
throw std::runtime_error(strerror(errno)); {
throw errno_exception(strerror(errno), errno);
}
} }
static void to_lwip_sockaddr(sockaddr_in &addr, const socket_address_t &socket_addr) static void to_lwip_sockaddr(sockaddr_in &addr, const socket_address_t &socket_addr)
@ -104,6 +107,10 @@ public:
lwip_close(sock_); lwip_close(sock_);
} }
virtual void install() override
{
}
virtual object_accessor<network_socket> accept(socket_address_t *remote_address) override virtual object_accessor<network_socket> accept(socket_address_t *remote_address) override
{ {
object_ptr<k_network_socket> socket(std::in_place, new k_network_socket()); object_ptr<k_network_socket> socket(std::in_place, new k_network_socket());
@ -260,6 +267,25 @@ public:
return ret; return ret;
} }
virtual int fcntl(int cmd, int val) override
{
auto ret = lwip_fcntl(sock_, cmd, val);
check_lwip_error(ret);
return ret;
}
virtual void select(fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout) override
{
check_lwip_error(lwip_select(sock_ + 1, readset, writeset, exceptset, timeout));
}
virtual int control(uint32_t control_code, gsl::span<const uint8_t> write_buffer, gsl::span<uint8_t> read_buffer) override
{
int val = *reinterpret_cast<const int *>(write_buffer.data());
check_lwip_error(lwip_ioctl(sock_, (unsigned int)control_code, &val));
return 0;
}
private: private:
k_network_socket() k_network_socket()
: sock_(0) : sock_(0)
@ -276,7 +302,11 @@ private:
auto f = obj.as<k_network_socket>(); auto f = obj.as<k_network_socket>();
#define CATCH_ALL \ #define CATCH_ALL \
catch (...) { return -1; } catch (errno_exception &e) \
{ \
errno = e.code(); \
return -1; \
}
#define CHECK_ARG(x) \ #define CHECK_ARG(x) \
if (!x) \ if (!x) \
@ -411,6 +441,29 @@ int network_socket_receive_from(handle_t socket_handle, uint8_t *data, size_t le
CATCH_ALL; CATCH_ALL;
} }
int network_socket_fcntl(handle_t socket_handle, int cmd, int val)
{
try
{
SOCKET_ENTRY;
return f->fcntl(cmd, val);
}
CATCH_ALL;
}
int network_socket_select(int socket_handle, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout)
{
try
{
SOCKET_ENTRY;
f->select(readset, writeset, exceptset, timeout);
return 0;
}
CATCH_ALL;
}
int network_socket_addr_parse(const char *ip_addr, int port, uint8_t *socket_addr) int network_socket_addr_parse(const char *ip_addr, int port, uint8_t *socket_addr)
{ {
try try

View File

@ -202,9 +202,9 @@ configIDLE_TASK_NAME in FreeRTOSConfig.h. */
UBaseType_t uxTopPriority; \ UBaseType_t uxTopPriority; \
\ \
/* Find the highest priority list that contains ready tasks. */ \ /* Find the highest priority list that contains ready tasks. */ \
portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority ); \ portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority[uxPsrId] ); \
configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 ); \ configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[uxPsrId][ uxTopPriority ] ) ) > 0 ); \
listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) ); \ listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB[uxPsrId], &( pxReadyTasksLists[uxPsrId][ uxTopPriority ] ) ); \
} /* taskSELECT_HIGHEST_PRIORITY_TASK() */ } /* taskSELECT_HIGHEST_PRIORITY_TASK() */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -214,9 +214,9 @@ configIDLE_TASK_NAME in FreeRTOSConfig.h. */
or suspended list then it won't be in a ready list. */ or suspended list then it won't be in a ready list. */
#define taskRESET_READY_PRIORITY( uxPriority ) \ #define taskRESET_READY_PRIORITY( uxPriority ) \
{ \ { \
if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \ if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[uxPsrId][ ( uxPriority ) ] ) ) == ( UBaseType_t ) 0 ) \
{ \ { \
portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority ) ); \ portRESET_READY_PRIORITY( ( uxPriority ), ( uxTopReadyPriority[uxPsrId] ) ); \
} \ } \
} }
@ -1108,7 +1108,7 @@ void vAddNewTaskToCurrentReadyList(TaskHandle_t pxNewTaskHandle)
#if ( configUSE_TRACE_FACILITY == 1 ) #if ( configUSE_TRACE_FACILITY == 1 )
{ {
/* Add a counter into the TCB for tracing only. */ /* Add a counter into the TCB for tracing only. */
pxNewTCB->uxTCBNumber = uxTaskNumber; pxNewTCB->uxTCBNumber = uxTaskNumber[uxPsrId];
} }
#endif /* configUSE_TRACE_FACILITY */ #endif /* configUSE_TRACE_FACILITY */
traceTASK_CREATE( pxNewTCB ); traceTASK_CREATE( pxNewTCB );
@ -1979,7 +1979,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
pxIdleTaskStackBuffer, pxIdleTaskStackBuffer,
pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */ pxIdleTaskTCBBuffer ); /*lint !e961 MISRA exception, justified as it is not a redundant explicit cast to all supported compilers. */
if( xIdleTaskHandle != NULL ) if( xIdleTaskHandle[uxPsrId] != NULL )
{ {
xReturn = pdPASS; xReturn = pdPASS;
} }
@ -2073,7 +2073,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
/* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0, /* Prevent compiler warnings if INCLUDE_xTaskGetIdleTaskHandle is set to 0,
meaning xIdleTaskHandle is not used anywhere else. */ meaning xIdleTaskHandle is not used anywhere else. */
( void ) xIdleTaskHandle; ( void ) xIdleTaskHandle[uxPsrId];
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -2412,7 +2412,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
{ {
UBaseType_t uxQueue = configMAX_PRIORITIES; UBaseType_t uxQueue = configMAX_PRIORITIES;
TCB_t* pxTCB; TCB_t* pxTCB;
UBaseType_t uxPsrId = uxPortGetProcessorId();
/* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */ /* Task names will be truncated to configMAX_TASK_NAME_LEN - 1 bytes. */
configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN ); configASSERT( strlen( pcNameToQuery ) < configMAX_TASK_NAME_LEN );
@ -2422,7 +2422,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
do do
{ {
uxQueue--; uxQueue--;
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[ uxQueue ] ), pcNameToQuery ); pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) &( pxReadyTasksLists[uxPsrId][ uxQueue ] ), pcNameToQuery );
if( pxTCB != NULL ) if( pxTCB != NULL )
{ {
@ -2435,12 +2435,12 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
/* Search the delayed lists. */ /* Search the delayed lists. */
if( pxTCB == NULL ) if( pxTCB == NULL )
{ {
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList, pcNameToQuery ); pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxDelayedTaskList[uxPsrId], pcNameToQuery );
} }
if( pxTCB == NULL ) if( pxTCB == NULL )
{ {
pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList, pcNameToQuery ); pxTCB = prvSearchForNameWithinSingleList( ( List_t * ) pxOverflowDelayedTaskList[uxPsrId], pcNameToQuery );
} }
#if ( INCLUDE_vTaskSuspend == 1 ) #if ( INCLUDE_vTaskSuspend == 1 )
@ -2448,7 +2448,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
if( pxTCB == NULL ) if( pxTCB == NULL )
{ {
/* Search the suspended list. */ /* Search the suspended list. */
pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList, pcNameToQuery ); pxTCB = prvSearchForNameWithinSingleList( &xSuspendedTaskList[uxPsrId], pcNameToQuery );
} }
} }
#endif #endif
@ -2458,7 +2458,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
if( pxTCB == NULL ) if( pxTCB == NULL )
{ {
/* Search the deleted list. */ /* Search the deleted list. */
pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination, pcNameToQuery ); pxTCB = prvSearchForNameWithinSingleList( &xTasksWaitingTermination[uxPsrId], pcNameToQuery );
} }
} }
#endif #endif
@ -2476,31 +2476,31 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime ) UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t * const pulTotalRunTime )
{ {
UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES; UBaseType_t uxTask = 0, uxQueue = configMAX_PRIORITIES;
UBaseType_t uxPsrId = uxPortGetProcessorId();
vTaskSuspendAll(); vTaskSuspendAll();
{ {
/* Is there a space in the array for each task in the system? */ /* Is there a space in the array for each task in the system? */
if( uxArraySize >= uxCurrentNumberOfTasks ) if( uxArraySize >= uxCurrentNumberOfTasks[uxPsrId] )
{ {
/* Fill in an TaskStatus_t structure with information on each /* Fill in an TaskStatus_t structure with information on each
task in the Ready state. */ task in the Ready state. */
do do
{ {
uxQueue--; uxQueue--;
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[ uxQueue ] ), eReady ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &( pxReadyTasksLists[uxPsrId][ uxQueue ] ), eReady );
} while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ } while( uxQueue > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Fill in an TaskStatus_t structure with information on each /* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */ task in the Blocked state. */
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList, eBlocked ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxDelayedTaskList[uxPsrId], eBlocked );
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList, eBlocked ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), ( List_t * ) pxOverflowDelayedTaskList[uxPsrId], eBlocked );
#if( INCLUDE_vTaskDelete == 1 ) #if( INCLUDE_vTaskDelete == 1 )
{ {
/* Fill in an TaskStatus_t structure with information on /* Fill in an TaskStatus_t structure with information on
each task that has been deleted but not yet cleaned up. */ each task that has been deleted but not yet cleaned up. */
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination, eDeleted ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xTasksWaitingTermination[uxPsrId], eDeleted );
} }
#endif #endif
@ -2508,7 +2508,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
{ {
/* Fill in an TaskStatus_t structure with information on /* Fill in an TaskStatus_t structure with information on
each task in the Suspended state. */ each task in the Suspended state. */
uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList, eSuspended ); uxTask += prvListTasksWithinSingleList( &( pxTaskStatusArray[ uxTask ] ), &xSuspendedTaskList[uxPsrId], eSuspended );
} }
#endif #endif
@ -2549,10 +2549,11 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
TaskHandle_t xTaskGetIdleTaskHandle( void ) TaskHandle_t xTaskGetIdleTaskHandle( void )
{ {
UBaseType_t uxPsrId = uxPortGetProcessorId();
/* If xTaskGetIdleTaskHandle() is called before the scheduler has been /* If xTaskGetIdleTaskHandle() is called before the scheduler has been
started, then xIdleTaskHandle will be NULL. */ started, then xIdleTaskHandle will be NULL. */
configASSERT( ( xIdleTaskHandle != NULL ) ); configASSERT( ( xIdleTaskHandle[uxPsrId] != NULL ) );
return xIdleTaskHandle; return xIdleTaskHandle[uxPsrId];
} }
#endif /* INCLUDE_xTaskGetIdleTaskHandle */ #endif /* INCLUDE_xTaskGetIdleTaskHandle */
@ -2942,9 +2943,9 @@ void vTaskSwitchContext( void )
#if ( configGENERATE_RUN_TIME_STATS == 1 ) #if ( configGENERATE_RUN_TIME_STATS == 1 )
{ {
#ifdef portALT_GET_RUN_TIME_COUNTER_VALUE #ifdef portALT_GET_RUN_TIME_COUNTER_VALUE
portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime ); portALT_GET_RUN_TIME_COUNTER_VALUE( ulTotalRunTime[uxPsrId] );
#else #else
ulTotalRunTime = portGET_RUN_TIME_COUNTER_VALUE(); ulTotalRunTime[uxPsrId] = portGET_RUN_TIME_COUNTER_VALUE();
#endif #endif
/* Add the amount of time the task has been running to the /* Add the amount of time the task has been running to the
@ -2954,15 +2955,15 @@ void vTaskSwitchContext( void )
overflows. The guard against negative values is to protect overflows. The guard against negative values is to protect
against suspect run time stat counter implementations - which against suspect run time stat counter implementations - which
are provided by the application, not the kernel. */ are provided by the application, not the kernel. */
if( ulTotalRunTime > ulTaskSwitchedInTime ) if( ulTotalRunTime[uxPsrId] > ulTaskSwitchedInTime[uxPsrId] )
{ {
pxCurrentTCB->ulRunTimeCounter += ( ulTotalRunTime - ulTaskSwitchedInTime ); pxCurrentTCB[uxPsrId]->ulRunTimeCounter += ( ulTotalRunTime[uxPsrId] - ulTaskSwitchedInTime[uxPsrId] );
} }
else else
{ {
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
ulTaskSwitchedInTime = ulTotalRunTime; ulTaskSwitchedInTime[uxPsrId] = ulTotalRunTime[uxPsrId];
} }
#endif /* configGENERATE_RUN_TIME_STATS */ #endif /* configGENERATE_RUN_TIME_STATS */
@ -3055,7 +3056,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, const TickType_t xIte
xTicksToWait = portMAX_DELAY; xTicksToWait = portMAX_DELAY;
} }
traceTASK_DELAY_UNTIL( ( xTickCount + xTicksToWait ) ); traceTASK_DELAY_UNTIL( ( xTickCount[uxPsrId] + xTicksToWait ) );
prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely ); prvAddCurrentTaskToDelayedList( xTicksToWait, xWaitIndefinitely );
} }
@ -3513,6 +3514,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions ) void vTaskAllocateMPURegions( TaskHandle_t xTaskToModify, const MemoryRegion_t * const xRegions )
{ {
TCB_t *pxTCB; TCB_t *pxTCB;
UBaseType_t uxPsrId = uxPortGetProcessorId();
/* If null is passed in here then we are modifying the MPU settings of /* If null is passed in here then we are modifying the MPU settings of
the calling task. */ the calling task. */
@ -3592,7 +3594,7 @@ static void prvCheckTasksWaitingTermination( void )
void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState ) void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState )
{ {
TCB_t *pxTCB; TCB_t *pxTCB;
UBaseType_t uxPsrId = uxPortGetProcessorId();
/* xTask is NULL then get the state of the calling task. */ /* xTask is NULL then get the state of the calling task. */
pxTCB = prvGetTCBFromHandle( xTask ); pxTCB = prvGetTCBFromHandle( xTask );
@ -3627,7 +3629,7 @@ static void prvCheckTasksWaitingTermination( void )
state is just set to whatever is passed in. */ state is just set to whatever is passed in. */
if( eState != eInvalid ) if( eState != eInvalid )
{ {
if( pxTCB == pxCurrentTCB ) if( pxTCB == pxCurrentTCB[uxPsrId] )
{ {
pxTaskStatus->eCurrentState = eRunning; pxTaskStatus->eCurrentState = eRunning;
} }
@ -3869,7 +3871,7 @@ UBaseType_t uxPsrId = uxPortGetProcessorId();
{ {
BaseType_t xReturn; BaseType_t xReturn;
if( xSchedulerRunning == pdFALSE ) if( xSchedulerRunning[uxPortGetProcessorId()] == pdFALSE )
{ {
xReturn = taskSCHEDULER_NOT_STARTED; xReturn = taskSCHEDULER_NOT_STARTED;
} }
@ -4270,7 +4272,7 @@ uint32_t mstatus_t = 0;
TaskStatus_t *pxTaskStatusArray; TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x; volatile UBaseType_t uxArraySize, x;
char cStatus; char cStatus;
UBaseType_t uxPsrId = uxPortGetProcessorId();
/* /*
* PLEASE NOTE: * PLEASE NOTE:
* *
@ -4301,12 +4303,12 @@ uint32_t mstatus_t = 0;
/* Take a snapshot of the number of tasks in case it changes while this /* Take a snapshot of the number of tasks in case it changes while this
function is executing. */ function is executing. */
uxArraySize = uxCurrentNumberOfTasks; uxArraySize = uxCurrentNumberOfTasks[uxPsrId];
/* Allocate an array index for each task. NOTE! if /* Allocate an array index for each task. NOTE! if
configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
equate to NULL. */ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks[uxPsrId] * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
@ -4368,7 +4370,7 @@ uint32_t mstatus_t = 0;
TaskStatus_t *pxTaskStatusArray; TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize, x; volatile UBaseType_t uxArraySize, x;
uint32_t ulTotalTime, ulStatsAsPercentage; uint32_t ulTotalTime, ulStatsAsPercentage;
UBaseType_t uxPsrId = uxPortGetProcessorId();
#if( configUSE_TRACE_FACILITY != 1 ) #if( configUSE_TRACE_FACILITY != 1 )
{ {
#error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats(). #error configUSE_TRACE_FACILITY must also be set to 1 in FreeRTOSConfig.h to use vTaskGetRunTimeStats().
@ -4405,12 +4407,12 @@ uint32_t mstatus_t = 0;
/* Take a snapshot of the number of tasks in case it changes while this /* Take a snapshot of the number of tasks in case it changes while this
function is executing. */ function is executing. */
uxArraySize = uxCurrentNumberOfTasks; uxArraySize = uxCurrentNumberOfTasks[uxPsrId];
/* Allocate an array index for each task. NOTE! If /* Allocate an array index for each task. NOTE! If
configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will configSUPPORT_DYNAMIC_ALLOCATION is set to 0 then pvPortMalloc() will
equate to NULL. */ equate to NULL. */
pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks * sizeof( TaskStatus_t ) ); pxTaskStatusArray = pvPortMalloc( uxCurrentNumberOfTasks[uxPsrId] * sizeof( TaskStatus_t ) );
if( pxTaskStatusArray != NULL ) if( pxTaskStatusArray != NULL )
{ {
@ -5107,24 +5109,24 @@ const TickType_t xConstTickCount = xTickCount[uxPsrId];
xTimeToWake = xConstTickCount + xTicksToWait; xTimeToWake = xConstTickCount + xTicksToWait;
/* The list item will be inserted in wake time order. */ /* The list item will be inserted in wake time order. */
listSET_LIST_ITEM_VALUE( &( pxCurrentTCB->xStateListItem ), xTimeToWake ); listSET_LIST_ITEM_VALUE( &( pxCurrentTCB[uxPsrId]->xStateListItem ), xTimeToWake );
if( xTimeToWake < xConstTickCount ) if( xTimeToWake < xConstTickCount )
{ {
/* Wake time has overflowed. Place this item in the overflow list. */ /* Wake time has overflowed. Place this item in the overflow list. */
vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); vListInsert( pxOverflowDelayedTaskList[uxPsrId], &( pxCurrentTCB[uxPsrId]->xStateListItem ) );
} }
else else
{ {
/* The wake time has not overflowed, so the current block list is used. */ /* The wake time has not overflowed, so the current block list is used. */
vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) ); vListInsert( pxDelayedTaskList[uxPsrId], &( pxCurrentTCB[uxPsrId]->xStateListItem ) );
/* If the task entering the blocked state was placed at the head of the /* If the task entering the blocked state was placed at the head of the
list of blocked tasks then xNextTaskUnblockTime needs to be updated list of blocked tasks then xNextTaskUnblockTime needs to be updated
too. */ too. */
if( xTimeToWake < xNextTaskUnblockTime ) if( xTimeToWake < xNextTaskUnblockTime[uxPsrId] )
{ {
xNextTaskUnblockTime = xTimeToWake; xNextTaskUnblockTime[uxPsrId] = xTimeToWake;
} }
else else
{ {

View File

@ -0,0 +1,51 @@
/* Copyright 2018 Canaan Inc.
*
* 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 _POSIX_SYS_IOCTL_H
#define _POSIX_SYS_IOCTL_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define IOCPARM_MASK 0x7fU /* parameters must be < 128 bytes */
#define IOC_VOID 0x20000000UL /* no parameters */
#define IOC_OUT 0x40000000UL /* copy out parameters */
#define IOC_IN 0x80000000UL /* copy in parameters */
#define IOC_INOUT (IOC_IN | IOC_OUT) /* 0x20000000 distinguishes new & old ioctl's */
#define _IO(x, y) (IOC_VOID | ((x) << 8) | (y))
#define _IOR(x, y, t) (IOC_OUT | (((unsigned int)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
#define _IOW(x, y, t) (IOC_IN | (((unsigned int)sizeof(t) & IOCPARM_MASK) << 16) | ((x) << 8) | (y))
#ifndef FIONREAD
#define FIONREAD _IOR('f', 127, unsigned int) /* get # bytes to read */
#endif
#ifndef FIONBIO
#define FIONBIO _IOW('f', 126, unsigned int) /* set/clear non-blocking i/o */
#endif
int ioctl(int handle, unsigned int cmd, void *argp);
#ifdef __cplusplus
}
#endif
#endif

46
lib/posix/ioctl.cpp Normal file
View File

@ -0,0 +1,46 @@
/* Copyright 2018 Canaan Inc.
*
* 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 "sys/ioctl.h"
#include "utils.h"
#include <kernel/driver_impl.hpp>
#include <network.h>
#include <string.h>
#include <sys/socket.h>
using namespace sys;
#define CATCH_ALL \
catch (errno_exception &e) \
{ \
errno = e.code(); \
return -1; \
}
int ioctl(int handle, unsigned int cmd, void *argp)
{
try
{
auto &obj = system_handle_to_object(handle); \
configASSERT(obj.is<custom_driver>()); \
auto f = obj.as<custom_driver>();
const int val = *(int *)argp;
f->control((uint32_t)cmd, { (const uint8_t *)&val, 4L }, { NULL, 0L });
return 0;
}
CATCH_ALL;
}

View File

@ -17,6 +17,7 @@
#include <kernel/driver_impl.hpp> #include <kernel/driver_impl.hpp>
#include <network.h> #include <network.h>
#include <string.h> #include <string.h>
#include <sys/select.h>
using namespace sys; using namespace sys;
@ -25,8 +26,12 @@ using namespace sys;
configASSERT(obj.is<network_socket>()); \ configASSERT(obj.is<network_socket>()); \
auto f = obj.as<network_socket>(); auto f = obj.as<network_socket>();
#define CATCH_ALL \ #define CATCH_ALL \
catch (...) { return -1; } catch (errno_exception & e) \
{ \
errno = e.code(); \
return -1; \
}
#define CHECK_ARG(x) \ #define CHECK_ARG(x) \
if (!x) \ if (!x) \
@ -279,3 +284,16 @@ int sendto(int socket, const void *data, size_t size, int flags, const struct so
} }
CATCH_ALL; CATCH_ALL;
} }
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout)
{
try
{
int socket = maxfdp1 - 1;
SOCKET_ENTRY;
f->select(readset, writeset, exceptset, timeout);
return 0;
}
CATCH_ALL;
}

View File

@ -522,14 +522,14 @@ alloc_socket(struct netconn *newconn, int accepted)
after having marked it as used. */ after having marked it as used. */
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
sockets[i].lastdata.pbuf = NULL; sockets[i].lastdata.pbuf = NULL;
#if LWIP_SOCKET_SELECT #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL
LWIP_ASSERT("sockets[i].select_waiting == 0", sockets[i].select_waiting == 0); LWIP_ASSERT("sockets[i].select_waiting == 0", sockets[i].select_waiting == 0);
sockets[i].rcvevent = 0; sockets[i].rcvevent = 0;
/* TCP sendbuf is empty, but the socket is not yet writable until connected /* TCP sendbuf is empty, but the socket is not yet writable until connected
* (unless it has been created by accept()). */ * (unless it has been created by accept()). */
sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1); sockets[i].sendevent = (NETCONNTYPE_GROUP(newconn->type) == NETCONN_TCP ? (accepted != 0) : 1);
sockets[i].errevent = 0; sockets[i].errevent = 0;
#endif /* LWIP_SOCKET_SELECT */ #endif /* LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL */
return i + LWIP_SOCKET_OFFSET; return i + LWIP_SOCKET_OFFSET;
} }
SYS_ARCH_UNPROTECT(lev); SYS_ARCH_UNPROTECT(lev);
@ -1305,7 +1305,7 @@ lwip_recvmsg(int s, struct msghdr *message, int flags)
if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) || if ((message->msg_iov[i].iov_base == NULL) || ((ssize_t)message->msg_iov[i].iov_len <= 0) ||
((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) || ((size_t)(ssize_t)message->msg_iov[i].iov_len != message->msg_iov[i].iov_len) ||
((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) { ((ssize_t)(buflen + (ssize_t)message->msg_iov[i].iov_len) <= 0)) {
sock_set_errno(sock, ERR_VAL); sock_set_errno(sock, err_to_errno(ERR_VAL));
done_socket(sock); done_socket(sock);
return -1; return -1;
} }
@ -2304,7 +2304,6 @@ lwip_poll_dec_sockets_used(struct pollfd *fds, nfds_t nfds)
/* Go through each struct pollfd in the array. */ /* Go through each struct pollfd in the array. */
for (fdi = 0; fdi < nfds; fdi++) { for (fdi = 0; fdi < nfds; fdi++) {
struct lwip_sock *sock = tryget_socket_unconn_nouse(fds[fdi].fd); struct lwip_sock *sock = tryget_socket_unconn_nouse(fds[fdi].fd);
LWIP_ASSERT("socket gone at the end of select", sock != NULL);
if (sock != NULL) { if (sock != NULL) {
done_socket(sock); done_socket(sock);
} }
@ -3741,7 +3740,7 @@ lwip_setsockopt_impl(int s, int level, int optname, const void *optval, socklen_
} }
int int
lwip_ioctl(int s, long cmd, void *argp) lwip_ioctl(int s, unsigned int cmd, void *argp)
{ {
struct lwip_sock *sock = get_socket(s); struct lwip_sock *sock = get_socket(s);
u8_t val; u8_t val;
@ -3808,7 +3807,7 @@ lwip_ioctl(int s, long cmd, void *argp)
#endif /* LWIP_SO_RCVBUF */ #endif /* LWIP_SO_RCVBUF */
#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */
case (long)FIONBIO: case FIONBIO:
val = 0; val = 0;
if (argp && *(int *)argp) { if (argp && *(int *)argp) {
val = 1; val = 1;

View File

@ -214,7 +214,7 @@ ip4_route(const ip4_addr_t *dest)
#endif /* !LWIP_SINGLE_NETIF */ #endif /* !LWIP_SINGLE_NETIF */
if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) || if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||
ip4_addr_isany_val(*netif_ip4_addr(netif_default))) { ip4_addr_isany_val(*netif_ip4_addr(netif_default)) || ip4_addr_isloopback(dest)) {
/* No matching netif found and default netif is not usable. /* No matching netif found and default netif is not usable.
If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */ If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip4_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",

View File

@ -583,6 +583,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
tcp_free(pcb); tcp_free(pcb);
} else { } else {
int send_rst = 0; int send_rst = 0;
u16_t local_port = 0;
enum tcp_state last_state; enum tcp_state last_state;
seqno = pcb->snd_nxt; seqno = pcb->snd_nxt;
ackno = pcb->rcv_nxt; ackno = pcb->rcv_nxt;
@ -597,6 +598,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
} }
} else { } else {
send_rst = reset; send_rst = reset;
local_port = pcb->local_port;
TCP_PCB_REMOVE_ACTIVE(pcb); TCP_PCB_REMOVE_ACTIVE(pcb);
} }
if (pcb->unacked != NULL) { if (pcb->unacked != NULL) {
@ -613,7 +615,7 @@ tcp_abandon(struct tcp_pcb *pcb, int reset)
tcp_backlog_accepted(pcb); tcp_backlog_accepted(pcb);
if (send_rst) { if (send_rst) {
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n")); LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_abandon: sending RST\n"));
tcp_rst(pcb, seqno, ackno, &pcb->local_ip, &pcb->remote_ip, pcb->local_port, pcb->remote_port); tcp_rst(pcb, seqno, ackno, &pcb->local_ip, &pcb->remote_ip, local_port, pcb->remote_port);
} }
last_state = pcb->state; last_state = pcb->state;
tcp_free(pcb); tcp_free(pcb);
@ -966,6 +968,7 @@ void
tcp_recved(struct tcp_pcb *pcb, u16_t len) tcp_recved(struct tcp_pcb *pcb, u16_t len)
{ {
u32_t wnd_inflation; u32_t wnd_inflation;
tcpwnd_size_t rcv_wnd;
LWIP_ASSERT_CORE_LOCKED(); LWIP_ASSERT_CORE_LOCKED();
@ -975,19 +978,13 @@ tcp_recved(struct tcp_pcb *pcb, u16_t len)
LWIP_ASSERT("don't call tcp_recved for listen-pcbs", LWIP_ASSERT("don't call tcp_recved for listen-pcbs",
pcb->state != LISTEN); pcb->state != LISTEN);
pcb->rcv_wnd = (tcpwnd_size_t)(pcb->rcv_wnd + len); rcv_wnd = (tcpwnd_size_t)(pcb->rcv_wnd + len);
if (pcb->rcv_wnd > TCP_WND_MAX(pcb)) { if ((rcv_wnd > TCP_WND_MAX(pcb)) || (rcv_wnd < pcb->rcv_wnd)) {
/* window got too big or tcpwnd_size_t overflow */
LWIP_DEBUGF(TCP_DEBUG, ("tcp_recved: window got too big or tcpwnd_size_t overflow\n"));
pcb->rcv_wnd = TCP_WND_MAX(pcb); pcb->rcv_wnd = TCP_WND_MAX(pcb);
} else if (pcb->rcv_wnd == 0) { } else {
/* rcv_wnd overflowed */ pcb->rcv_wnd = rcv_wnd;
if (TCP_STATE_IS_CLOSING(pcb->state)) {
/* In passive close, we allow this, since the FIN bit is added to rcv_wnd
by the stack itself, since it is not mandatory for an application
to call tcp_recved() for the FIN bit, but e.g. the netconn API does so. */
pcb->rcv_wnd = TCP_WND_MAX(pcb);
} else {
LWIP_ASSERT("tcp_recved: len wrapped rcv_wnd\n", 0);
}
} }
wnd_inflation = tcp_update_rcv_ann_wnd(pcb); wnd_inflation = tcp_update_rcv_ann_wnd(pcb);
@ -1219,6 +1216,7 @@ tcp_slowtmr_start:
LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT); LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);
if (pcb->last_timer == tcp_timer_ctr) { if (pcb->last_timer == tcp_timer_ctr) {
/* skip this pcb, we have already processed it */ /* skip this pcb, we have already processed it */
prev = pcb;
pcb = pcb->next; pcb = pcb->next;
continue; continue;
} }

View File

@ -1290,7 +1290,7 @@
* an upper limit on the MSS advertised by the remote host. * an upper limit on the MSS advertised by the remote host.
*/ */
#if !defined TCP_MSS || defined __DOXYGEN__ #if !defined TCP_MSS || defined __DOXYGEN__
#define TCP_MSS 536 #define TCP_MSS 1536
#endif #endif
/** /**
@ -1763,7 +1763,7 @@
* sys_thread_new() when the thread is created. * sys_thread_new() when the thread is created.
*/ */
#if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__ #if !defined TCPIP_THREAD_PRIO || defined __DOXYGEN__
#define TCPIP_THREAD_PRIO 1 #define TCPIP_THREAD_PRIO 2
#endif #endif
/** /**

View File

@ -407,27 +407,27 @@ typedef struct ipv6_mreq {
#define IOC_INOUT (IOC_IN|IOC_OUT) #define IOC_INOUT (IOC_IN|IOC_OUT)
/* 0x20000000 distinguishes new & /* 0x20000000 distinguishes new &
old ioctl's */ old ioctl's */
#define _IO(x,y) ((long)(IOC_VOID|((x)<<8)|(y))) #define _IO(x,y) ((unsigned int)(IOC_VOID|((x)<<8)|(y)))
#define _IOR(x,y,t) ((long)(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))) #define _IOR(x,y,t) ((unsigned int)(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)))
#define _IOW(x,y,t) ((long)(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))) #define _IOW(x,y,t) ((unsigned int)(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y)))
#endif /* !defined(FIONREAD) || !defined(FIONBIO) */ #endif /* !defined(FIONREAD) || !defined(FIONBIO) */
#ifndef FIONREAD #ifndef FIONREAD
#define FIONREAD _IOR('f', 127, unsigned long) /* get # bytes to read */ #define FIONREAD _IOR('f', 127, unsigned int) /* get # bytes to read */
#endif #endif
#ifndef FIONBIO #ifndef FIONBIO
#define FIONBIO _IOW('f', 126, unsigned long) /* set/clear non-blocking i/o */ #define FIONBIO _IOW('f', 126, unsigned int) /* set/clear non-blocking i/o */
#endif #endif
/* Socket I/O Controls: unimplemented */ /* Socket I/O Controls: unimplemented */
#ifndef SIOCSHIWAT #ifndef SIOCSHIWAT
#define SIOCSHIWAT _IOW('s', 0, unsigned long) /* set high watermark */ #define SIOCSHIWAT _IOW('s', 0, unsigned int) /* set high watermark */
#define SIOCGHIWAT _IOR('s', 1, unsigned long) /* get high watermark */ #define SIOCGHIWAT _IOR('s', 1, unsigned int) /* get high watermark */
#define SIOCSLOWAT _IOW('s', 2, unsigned long) /* set low watermark */ #define SIOCSLOWAT _IOW('s', 2, unsigned int) /* set low watermark */
#define SIOCGLOWAT _IOR('s', 3, unsigned long) /* get low watermark */ #define SIOCGLOWAT _IOR('s', 3, unsigned int) /* get low watermark */
#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */ #define SIOCATMARK _IOR('s', 7, unsigned int) /* at oob mark? */
#endif #endif
/* commands for fnctl */ /* commands for fnctl */
@ -603,7 +603,7 @@ int lwip_select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptse
#if LWIP_SOCKET_POLL #if LWIP_SOCKET_POLL
int lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout); int lwip_poll(struct pollfd *fds, nfds_t nfds, int timeout);
#endif #endif
int lwip_ioctl(int s, long cmd, void *argp); int lwip_ioctl(int s, unsigned int cmd, void *argp);
int lwip_fcntl(int s, int cmd, int val); int lwip_fcntl(int s, int cmd, int val);
const char *lwip_inet_ntop(int af, const void *src, char *dst, socklen_t size); const char *lwip_inet_ntop(int af, const void *src, char *dst, socklen_t size);
int lwip_inet_pton(int af, const char *src, void *dst); int lwip_inet_pton(int af, const char *src, void *dst);