Updated EMAC test environment for LPCxx boards

Updated EMAC memory manager to use libservice nsdynmemlib
for EMAC memory buffers. Located the nsdynmemlib buffer heap
to DMA safe memory bank on LPCxx boards. Optimized placement of
static variables on EMAC test environment for LPCxx boards to
maximize available memory.
pull/7103/head
Mika Leppänen 2018-06-01 12:58:27 +03:00
parent 66e3409a37
commit 9095b037aa
5 changed files with 141 additions and 3 deletions

View File

@ -27,6 +27,11 @@
#include "rtos/Mutex.h" #include "rtos/Mutex.h"
extern "C" {
#include "arm_hal_interrupt_private.h"
}
#include "nsdynmemLIB.h"
#include "EMACMemoryManager.h" #include "EMACMemoryManager.h"
#include "emac_TestMemoryManager.h" #include "emac_TestMemoryManager.h"
@ -43,12 +48,57 @@
char s_trace_buffer[100] = MEM_MNGR_TRACE; 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() EmacTestMemoryManager::EmacTestMemoryManager()
: m_mem_mutex(), : m_mem_mutex(),
m_mem_buffers(), m_mem_buffers(),
m_alloc_unit(BUF_POOL_SIZE), m_alloc_unit(BUF_POOL_SIZE),
m_memory_available(true) 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) 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"); 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); buf->buffer = std::malloc(BUF_HEAD_SIZE + size + align + BUF_TAIL_SIZE);
#endif
CHECK_ASSERT(buf->buffer, "alloc_heap() no memory"); 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; emac_memory_t *next = mem_buf->next;
m_mem_buffers.erase(mem_buf_entry); m_mem_buffers.erase(mem_buf_entry);
#ifdef ETHMEM_SECTION
ns_dyn_mem_free(mem_buf->buffer);
#else
std::free(mem_buf->buffer); std::free(mem_buf->buffer);
#endif
delete mem_buf; delete mem_buf;
mem_buf = next; mem_buf = next;

View File

@ -39,6 +39,18 @@ nsapi_error_t EmacTestNetworkStack::add_dns_server(const SocketAddress &address)
return NSAPI_ERROR_OK; return NSAPI_ERROR_OK;
} }
nsapi_error_t EmacTestNetworkStack::call_in(int delay, mbed::Callback<void()> 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) nsapi_error_t EmacTestNetworkStack::socket_open(nsapi_socket_t *handle, nsapi_protocol_t proto)
{ {
return NSAPI_ERROR_OK; return NSAPI_ERROR_OK;

View File

@ -356,6 +356,38 @@ protected:
int optname, void *optval, unsigned *optlen); int optname, void *optval, unsigned *optlen);
private: private:
/** Call in callback
*
* Callback is used to call the call in method of the network stack.
*/
typedef mbed::Callback<nsapi_error_t (int delay_ms, mbed::Callback<void()> 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<void()> func);
Interface *m_interface; Interface *m_interface;
}; };

View File

@ -36,6 +36,32 @@
using namespace utest::v1; 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 { typedef struct {
int length; int length;
int receipt_number; int receipt_number;
@ -63,7 +89,12 @@ static int eth_mtu_size = 0;
// Event queue // Event queue
static rtos::Semaphore worker_loop_semaphore; static rtos::Semaphore worker_loop_semaphore;
static rtos::Semaphore link_status_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 void worker_loop_event_cb(int event);
static Event<void(int)> worker_loop_event(&worker_loop_event_queue, worker_loop_event_cb); static Event<void(int)> worker_loop_event(&worker_loop_event_queue, worker_loop_event_cb);
static void link_input_event_cb(void *buf); 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); void worker_loop(void);

View File

@ -58,7 +58,7 @@ extern const unsigned char eth_mac_broadcast_addr[];
#define RESET_ERROR_FLAGS(flags) emac_if_reset_error_flags(flags) #define RESET_ERROR_FLAGS(flags) emac_if_reset_error_flags(flags)
#define ETH_FRAME_HEADER_LEN 28 #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 ETH_MAC_ADDR_LEN 6
#define TIMEOUT 1 #define TIMEOUT 1