diff --git a/TESTS/netsocket/tcp/main.cpp b/TESTS/netsocket/tcp/main.cpp index 2eaa4d0cd7..45157b87d9 100644 --- a/TESTS/netsocket/tcp/main.cpp +++ b/TESTS/netsocket/tcp/main.cpp @@ -34,6 +34,9 @@ namespace NetworkInterface* net; } +char tcp_global::rx_buffer[RX_BUFF_SIZE]; +char tcp_global::tx_buffer[TX_BUFF_SIZE]; + NetworkInterface* get_interface() { return net; diff --git a/TESTS/netsocket/tcp/tcp_tests.h b/TESTS/netsocket/tcp/tcp_tests.h index f392ef7446..50e815d70b 100644 --- a/TESTS/netsocket/tcp/tcp_tests.h +++ b/TESTS/netsocket/tcp/tcp_tests.h @@ -24,6 +24,17 @@ void fill_tx_buffer_ascii(char *buff, size_t len); void tcpsocket_connect_to_echo_srv(TCPSocket& sock); void tcpsocket_connect_to_discard_srv(TCPSocket& sock); +namespace tcp_global +{ +static const int TCP_OS_STACK_SIZE = 1024; + +static const int RX_BUFF_SIZE = 1220; +static const int TX_BUFF_SIZE = 1220; + +extern char rx_buffer[RX_BUFF_SIZE]; +extern char tx_buffer[TX_BUFF_SIZE]; +} + /* * Test cases */ diff --git a/TESTS/netsocket/tcp/tcpsocket_echotest.cpp b/TESTS/netsocket/tcp/tcpsocket_echotest.cpp index bcd83035f7..013fd7172b 100644 --- a/TESTS/netsocket/tcp/tcpsocket_echotest.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_echotest.cpp @@ -31,9 +31,6 @@ namespace static const int SIGIO_TIMEOUT = 5000; //[ms] static const int BUFF_SIZE = 1200; - char rx_buffer[BUFF_SIZE] = {0}; - char tx_buffer[BUFF_SIZE] = {0}; - static const int PKTS = 22; static const int pkt_sizes[PKTS] = {1,2,3,4,5,6,7,8,9,10, \ 100,200,300,400,500,600,700,800,900,1000,\ @@ -54,9 +51,9 @@ void TCPSOCKET_ECHOTEST() int sent; int x = 0; for (int pkt_s = pkt_sizes[x]; x < PKTS; pkt_s = pkt_sizes[x++]) { - fill_tx_buffer_ascii(tx_buffer, BUFF_SIZE); + fill_tx_buffer_ascii(tcp_global::tx_buffer, BUFF_SIZE); - sent = sock.send(tx_buffer, pkt_s); + sent = sock.send(tcp_global::tx_buffer, pkt_s); if (sent < 0) { printf("[Round#%02d] network error %d\n", x, sent); TEST_FAIL(); @@ -64,14 +61,14 @@ void TCPSOCKET_ECHOTEST() int bytes2recv = sent; while (bytes2recv) { - recvd = sock.recv(&(rx_buffer[sent-bytes2recv]), bytes2recv); + recvd = sock.recv(&(tcp_global::rx_buffer[sent-bytes2recv]), bytes2recv); if (recvd < 0) { printf("[Round#%02d] network error %d\n", x, recvd); TEST_FAIL(); } bytes2recv -= recvd; } - TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, sent)); + TEST_ASSERT_EQUAL(0, memcmp(tcp_global::tx_buffer, tcp_global::rx_buffer, sent)); } TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close()); } @@ -81,7 +78,7 @@ void tcpsocket_echotest_nonblock_receiver(void *receive_bytes) int bytes2recv = *(int*)receive_bytes; int recvd; while (bytes2recv) { - recvd = sock.recv(&(rx_buffer[*(int*)receive_bytes-bytes2recv]), bytes2recv); + recvd = sock.recv(&(tcp_global::rx_buffer[*(int*)receive_bytes-bytes2recv]), bytes2recv); if (recvd == NSAPI_ERROR_WOULD_BLOCK) { wait(1); continue; @@ -91,7 +88,7 @@ void tcpsocket_echotest_nonblock_receiver(void *receive_bytes) bytes2recv -= recvd; } - TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, *(int*)receive_bytes)); + TEST_ASSERT_EQUAL(0, memcmp(tcp_global::tx_buffer, tcp_global::rx_buffer, *(int*)receive_bytes)); static int round = 0; printf("[Recevr#%02d] bytes received: %d\n", round++, *(int*)receive_bytes); @@ -110,22 +107,22 @@ void TCPSOCKET_ECHOTEST_NONBLOCK() int sent; int s_idx = 0; Thread *thread; - unsigned char *stack_mem = (unsigned char *)malloc(OS_STACK_SIZE); + unsigned char *stack_mem = (unsigned char *)malloc(tcp_global::TCP_OS_STACK_SIZE); TEST_ASSERT_NOT_NULL(stack_mem); for (int pkt_s = pkt_sizes[s_idx]; s_idx < PKTS; ++s_idx) { pkt_s = pkt_sizes[s_idx]; thread = new Thread(osPriorityNormal, - OS_STACK_SIZE, + tcp_global::TCP_OS_STACK_SIZE, stack_mem, "receiver"); TEST_ASSERT_EQUAL(osOK, thread->start(callback(tcpsocket_echotest_nonblock_receiver, &pkt_s))); - fill_tx_buffer_ascii(tx_buffer, pkt_s); + fill_tx_buffer_ascii(tcp_global::tx_buffer, pkt_s); bytes2send = pkt_s; while (bytes2send > 0) { - sent = sock.send(&(tx_buffer[pkt_s-bytes2send]), bytes2send); + sent = sock.send(&(tcp_global::tx_buffer[pkt_s-bytes2send]), bytes2send); if (sent == NSAPI_ERROR_WOULD_BLOCK) { TEST_ASSERT_NOT_EQUAL(osEventTimeout, osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status); continue; diff --git a/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp b/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp index adc3cdd0e8..12b8fdf403 100644 --- a/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp +++ b/TESTS/netsocket/tcp/tcpsocket_echotest_burst.cpp @@ -32,8 +32,6 @@ namespace static const int BURST_CNT = 100; static const int BURST_SIZE = 1220; - char rx_buffer[BURST_SIZE] = {0}; - char tx_buffer[BURST_SIZE] = {0}; } static void _sigio_handler(osThreadId id) { @@ -47,7 +45,7 @@ void TCPSOCKET_ECHOTEST_BURST() sock.sigio(callback(_sigio_handler, Thread::gettid())); // TX buffer to be preserved for comparison - fill_tx_buffer_ascii(tx_buffer, BURST_SIZE); + fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE); int recvd; int bt_left; @@ -55,7 +53,7 @@ void TCPSOCKET_ECHOTEST_BURST() for (int i = 0; i < BURST_CNT; i++) { bt_left = BURST_SIZE; while (bt_left > 0) { - sent = sock.send(&(tx_buffer[BURST_SIZE-bt_left]), bt_left); + sent = sock.send(&(tcp_global::tx_buffer[BURST_SIZE-bt_left]), bt_left); if (sent == NSAPI_ERROR_WOULD_BLOCK) { if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) { TEST_FAIL(); @@ -70,7 +68,7 @@ void TCPSOCKET_ECHOTEST_BURST() bt_left = BURST_SIZE; while (bt_left > 0) { - recvd = sock.recv(&(rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE); + recvd = sock.recv(&(tcp_global::rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE); if (recvd < 0) { printf("[%02d] network error %d\n", i, recvd); break; @@ -83,7 +81,7 @@ void TCPSOCKET_ECHOTEST_BURST() TEST_FAIL(); } - TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, BURST_SIZE)); + TEST_ASSERT_EQUAL(0, memcmp(tcp_global::tx_buffer, tcp_global::rx_buffer, BURST_SIZE)); } TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close()); } @@ -96,7 +94,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK() sock.sigio(callback(_sigio_handler, Thread::gettid())); // TX buffer to be preserved for comparison - fill_tx_buffer_ascii(tx_buffer, BURST_SIZE); + fill_tx_buffer_ascii(tcp_global::tx_buffer, BURST_SIZE); int sent; int recvd; @@ -104,7 +102,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK() for (int i = 0; i < BURST_CNT; i++) { bt_left = BURST_SIZE; while (bt_left > 0) { - sent = sock.send(&(tx_buffer[BURST_SIZE-bt_left]), bt_left); + sent = sock.send(&(tcp_global::tx_buffer[BURST_SIZE-bt_left]), bt_left); if (sent == NSAPI_ERROR_WOULD_BLOCK) { if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) { TEST_FAIL(); @@ -120,7 +118,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK() bt_left = BURST_SIZE; while (bt_left > 0) { - recvd = sock.recv(&(rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE); + recvd = sock.recv(&(tcp_global::rx_buffer[BURST_SIZE-bt_left]), BURST_SIZE); if (recvd == NSAPI_ERROR_WOULD_BLOCK) { if(osSignalWait(SIGNAL_SIGIO, SIGIO_TIMEOUT).status == osEventTimeout) { printf("[bt#%02d] packet timeout...", i); @@ -140,7 +138,7 @@ void TCPSOCKET_ECHOTEST_BURST_NONBLOCK() TEST_FAIL(); } - TEST_ASSERT_EQUAL(0, memcmp(tx_buffer, rx_buffer, BURST_SIZE)); + TEST_ASSERT_EQUAL(0, memcmp(tcp_global::tx_buffer, tcp_global::rx_buffer, BURST_SIZE)); } TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close()); } diff --git a/TESTS/network/emac/emac_TestMemoryManager.cpp b/TESTS/network/emac/emac_TestMemoryManager.cpp index 6a47454034..05a0a62663 100644 --- a/TESTS/network/emac/emac_TestMemoryManager.cpp +++ b/TESTS/network/emac/emac_TestMemoryManager.cpp @@ -27,6 +27,11 @@ #include "rtos/Mutex.h" +extern "C" { +#include "arm_hal_interrupt_private.h" +} +#include "nsdynmemLIB.h" + #include "EMACMemoryManager.h" #include "emac_TestMemoryManager.h" @@ -43,12 +48,57 @@ char s_trace_buffer[100] = MEM_MNGR_TRACE; +/* For LPC boards define the heap memory bank ourselves to give us section placement + control */ +#ifndef ETHMEM_SECTION +#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) +# if defined (__ICCARM__) +# define ETHMEM_SECTION +# elif defined(TOOLCHAIN_GCC_CR) +# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) +# else +# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) +# endif +#elif defined(TARGET_LPC1768) || defined(TARGET_LPC1769) +# if defined (__ICCARM__) +# define ETHMEM_SECTION +# elif defined(TOOLCHAIN_GCC_CR) +# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) +# else +# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned)) +# endif +#endif +#endif + +#ifdef ETHMEM_SECTION +// Use nanostack libservice dynamic memory library +#define EMAC_HEAP_SIZE 16300 + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#endif +ETHMEM_SECTION static unsigned char ns_heap[EMAC_HEAP_SIZE]; + +void emac_heap_error_handler(heap_fail_t event) +{ + MBED_ASSERT(0); +} +#endif + EmacTestMemoryManager::EmacTestMemoryManager() : m_mem_mutex(), m_mem_buffers(), m_alloc_unit(BUF_POOL_SIZE), m_memory_available(true) { +#ifdef ETHMEM_SECTION + static bool ns_heap_init = false; + if (!ns_heap_init) { + platform_critical_init(); // Create mutex for dynamic memory library + ns_dyn_mem_init(ns_heap, EMAC_HEAP_SIZE, emac_heap_error_handler, NULL); + ns_heap_init = true; + } +#endif } emac_mem_buf_t *EmacTestMemoryManager::alloc_heap(uint32_t size, uint32_t align) @@ -74,7 +124,11 @@ emac_mem_buf_t *EmacTestMemoryManager::alloc_heap(uint32_t size, uint32_t align, CHECK_ASSERT(buf, "alloc_heap() no memory"); +#ifdef ETHMEM_SECTION + buf->buffer = ns_dyn_mem_alloc(BUF_HEAD_SIZE + size + align + BUF_TAIL_SIZE); +#else buf->buffer = std::malloc(BUF_HEAD_SIZE + size + align + BUF_TAIL_SIZE); +#endif CHECK_ASSERT(buf->buffer, "alloc_heap() no memory"); @@ -218,7 +272,12 @@ void EmacTestMemoryManager::free(emac_mem_buf_t *buf) emac_memory_t *next = mem_buf->next; m_mem_buffers.erase(mem_buf_entry); + +#ifdef ETHMEM_SECTION + ns_dyn_mem_free(mem_buf->buffer); +#else std::free(mem_buf->buffer); +#endif delete mem_buf; mem_buf = next; diff --git a/TESTS/network/emac/emac_TestNetworkStack.cpp b/TESTS/network/emac/emac_TestNetworkStack.cpp index 9209f79492..cb5a2d2a2c 100644 --- a/TESTS/network/emac/emac_TestNetworkStack.cpp +++ b/TESTS/network/emac/emac_TestNetworkStack.cpp @@ -39,6 +39,18 @@ nsapi_error_t EmacTestNetworkStack::add_dns_server(const SocketAddress &address) return NSAPI_ERROR_OK; } +nsapi_error_t EmacTestNetworkStack::call_in(int delay, mbed::Callback func) +{ + // Implemented as empty to save memory + return NSAPI_ERROR_DEVICE_ERROR; +} + +EmacTestNetworkStack::call_in_callback_cb_t EmacTestNetworkStack::get_call_in_callback() +{ + call_in_callback_cb_t cb(this, &EmacTestNetworkStack::call_in); + return cb; +} + nsapi_error_t EmacTestNetworkStack::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto) { return NSAPI_ERROR_OK; diff --git a/TESTS/network/emac/emac_TestNetworkStack.h b/TESTS/network/emac/emac_TestNetworkStack.h index 8d325c6f89..d781d15190 100644 --- a/TESTS/network/emac/emac_TestNetworkStack.h +++ b/TESTS/network/emac/emac_TestNetworkStack.h @@ -356,6 +356,38 @@ protected: int optname, void *optval, unsigned *optlen); private: + + /** Call in callback + * + * Callback is used to call the call in method of the network stack. + */ + typedef mbed::Callback user_cb)> call_in_callback_cb_t; + + /** Get a call in callback + * + * Get a call in callback from the network stack context. + * + * Callback should not take more than 10ms to execute, otherwise it might + * prevent underlying thread processing. A portable user of the callback + * should not make calls to network operations due to stack size limitations. + * The callback should not perform expensive operations such as socket recv/send + * calls or blocking operations. + * + * @return Call in callback + */ + virtual call_in_callback_cb_t get_call_in_callback(); + + /** Call a callback after a delay + * + * Call a callback from the network stack context after a delay. If function + * returns error callback will not be called. + * + * @param delay Delay in milliseconds + * @param func Callback to be called + * @return 0 on success, negative error code on failure + */ + virtual nsapi_error_t call_in(int delay, mbed::Callback func); + Interface *m_interface; }; diff --git a/TESTS/network/emac/emac_util.cpp b/TESTS/network/emac/emac_util.cpp index 9bffd9cf65..23ece204ce 100644 --- a/TESTS/network/emac/emac_util.cpp +++ b/TESTS/network/emac/emac_util.cpp @@ -36,6 +36,32 @@ using namespace utest::v1; +/* For LPC boards define the memory bank ourselves to give us section placement + control */ +#ifndef ETHMEM_SECTION +#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) +# if defined (__ICCARM__) +# define ETHMEM_SECTION +# elif defined(TOOLCHAIN_GCC_CR) +# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) +# else +# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned)) +# endif +#elif defined(TARGET_LPC1768) || defined(TARGET_LPC1769) +# if defined (__ICCARM__) +# define ETHMEM_SECTION +# elif defined(TOOLCHAIN_GCC_CR) +# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) +# else +# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) +# endif +#endif +#endif + +#ifndef ETHMEM_SECTION +#define ETHMEM_SECTION +#endif + typedef struct { int length; int receipt_number; @@ -63,7 +89,12 @@ static int eth_mtu_size = 0; // Event queue static rtos::Semaphore worker_loop_semaphore; static rtos::Semaphore link_status_semaphore; -static EventQueue worker_loop_event_queue(20 * EVENTS_EVENT_SIZE); + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#endif +ETHMEM_SECTION static EventQueue worker_loop_event_queue(20 * EVENTS_EVENT_SIZE); + static void worker_loop_event_cb(int event); static Event worker_loop_event(&worker_loop_event_queue, worker_loop_event_cb); static void link_input_event_cb(void *buf); @@ -460,7 +491,11 @@ static void link_input_event_cb(void *buf) } } -static unsigned char thread_stack[2048]; + +#if defined (__ICCARM__) +#pragma location = ".ethusbram" +#endif +ETHMEM_SECTION static unsigned char thread_stack[2048]; void worker_loop(void); diff --git a/TESTS/network/emac/emac_util.h b/TESTS/network/emac/emac_util.h index 62b72fa022..08570341a3 100644 --- a/TESTS/network/emac/emac_util.h +++ b/TESTS/network/emac/emac_util.h @@ -58,7 +58,7 @@ extern const unsigned char eth_mac_broadcast_addr[]; #define RESET_ERROR_FLAGS(flags) emac_if_reset_error_flags(flags) #define ETH_FRAME_HEADER_LEN 28 -#define ETH_FRAME_MIN_LEN 60 +#define ETH_FRAME_MIN_LEN 60 + 4 #define ETH_MAC_ADDR_LEN 6 #define TIMEOUT 1