diff --git a/.github/workflows/greentea_cmake.yml b/.github/workflows/greentea_cmake.yml index 1f1893650e8..42c67eb2deb 100644 --- a/.github/workflows/greentea_cmake.yml +++ b/.github/workflows/greentea_cmake.yml @@ -146,7 +146,7 @@ jobs: # Note: We have to set a wifi network name and password so that the test will compile on devices that use wifi run: | rm -rf __build - cmake -S . -B __build -GNinja -DUPLOAD_METHOD=NONE -DMBED_GREENTEA_WIFI_SECURE_SSID=SomeNetwork -DMBED_GREENTEA_WIFI_SECURE_PASSWORD=SomePassword -DCMAKE_CTEST_ARGUMENTS="--output-on-failure;-V" -DMBED_BUILD_GREENTEA_TESTS=ON -DMBED_GREENTEA_TEST_BAREMETAL=ON -DMBED_GREENTEA_SERIAL_PORT=/dev/ttyDUMMY -DMBED_TARGET=${{ matrix.target }} -DMBED_APP_JSON_PATH=TESTS/configs/greentea_baremetal.json5 + cmake -S . -B __build -GNinja -DUPLOAD_METHOD=NONE -DMBED_GREENTEA_WIFI_SECURE_SSID=SomeNetwork -DMBED_GREENTEA_WIFI_SECURE_PASSWORD=SomePassword -DCMAKE_CTEST_ARGUMENTS="--output-on-failure;-V" -DMBED_BUILD_GREENTEA_TESTS=ON -DMBED_GREENTEA_SERIAL_PORT=/dev/ttyDUMMY -DMBED_TARGET=${{ matrix.target }} -DMBED_APP_JSON_PATH=TESTS/configs/greentea_baremetal.json5 cmake --build __build - name: Build ${{ matrix.target }} with full profile diff --git a/TESTS/configs/greentea_full.json5 b/TESTS/configs/greentea_full.json5 index d694798f93e..f8581195cef 100644 --- a/TESTS/configs/greentea_full.json5 +++ b/TESTS/configs/greentea_full.json5 @@ -18,6 +18,14 @@ "mbed-trace.enable": true, // Disable colored traces in tests, as the test runner does not like the terminal control chars - "mbed-trace.default-config": "TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN" + "mbed-trace.default-config": "TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN", + + // Don't use any network stack as the default, so that we can manually select which one + // is used in the tests. + "nsapi.default-stack": null, + + // Configure Nanostack for Ethernet mode only by default. This is sufficient for our tests and is + // needed because not every target has enough flash space for all of Nanostack (it can be more than 400kiB when you include the Mbed TLS deps it pulls in!) + "nanostack.configuration": "ethernet_host" } } diff --git a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp index 76cbe3861a9..34ddda1a744 100644 --- a/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp +++ b/connectivity/drivers/emac/TARGET_NXP_EMAC/TARGET_LPCTarget/lpc17_emac.cpp @@ -9,6 +9,7 @@ * * Copyright(C) 2011, NXP Semiconductor * All rights reserved. +* SPDX-License-Identifier: Apache-2.0 * *********************************************************************** * Software that is described herein is for illustrative purposes only @@ -127,7 +128,7 @@ struct lpc_enetdata { #if defined(TARGET_LPC17XX) # if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_ARM) -# define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) +# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned)) # endif #endif diff --git a/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/CMakeLists.txt b/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/CMakeLists.txt index b26af364e43..fd5544a7c58 100644 --- a/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/CMakeLists.txt +++ b/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/CMakeLists.txt @@ -22,6 +22,12 @@ target_sources(mbed-wifi mx_wifi/core/mx_wifi_slip.c ) +# This driver needs utility functions from LwIP +target_link_libraries(mbed-wifi + PRIVATE + mbed-lwipstack +) + # Link override object file coming from static library anyway # # NOTE: This linker option is to pretend undefined symbol and won't cause diff --git a/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/mx_wifi_mbed_os.cpp b/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/mx_wifi_mbed_os.cpp index ae60567d0a8..3519615ef85 100644 --- a/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/mx_wifi_mbed_os.cpp +++ b/connectivity/drivers/wifi/TARGET_STM/COMPONENT_EMW3080B/mx_wifi_mbed_os.cpp @@ -60,7 +60,7 @@ void mx_buf_set_size(mx_buf_t *p, int32_t n) mx_buf_t *mx_buf_alloc(uint32_t len) { - emac_mem_buf_t *p = emac3080b_global_memory_manager->alloc_pool(len, 0); + emac_mem_buf_t *p = emac3080b_global_memory_manager->alloc_heap(len, 0); return (mx_buf_t *) p; } diff --git a/connectivity/libraries/nanostack-libservice/CMakeLists.txt b/connectivity/libraries/nanostack-libservice/CMakeLists.txt index 24790c11ca6..3113ab32517 100644 --- a/connectivity/libraries/nanostack-libservice/CMakeLists.txt +++ b/connectivity/libraries/nanostack-libservice/CMakeLists.txt @@ -22,6 +22,10 @@ target_sources(mbed-nanostack-libservice source/nvmHelper/ns_nvm_helper.c ) +target_link_libraries(mbed-nanostack-libservice + PUBLIC + mbed-core-flags) + # The definition, source files and include directories below # are needed by mbed-trace which is part of the mbed-core CMake target target_compile_definitions(mbed-core-flags diff --git a/connectivity/libraries/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c b/connectivity/libraries/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c index a961b5a8ace..766c9decb59 100644 --- a/connectivity/libraries/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c +++ b/connectivity/libraries/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c @@ -21,6 +21,7 @@ #include "platform/arm_hal_interrupt.h" #include #include "ns_list.h" +#include "mbed_toolchain.h" #ifndef STANDARD_MALLOC typedef enum mem_stat_update_t { @@ -598,6 +599,10 @@ static bool pointer_address_validate(ns_mem_book_t *book, ns_mem_word_size_t *pt return false; } +// Hook from nanostack to the Mbed EMAC memory manager when memory becomes free. +MBED_WEAK void mbed_ns_heap_free_hook(void) +{} + void ns_mem_free(ns_mem_book_t *book, void *block) { #ifndef STANDARD_MALLOC @@ -633,6 +638,8 @@ void ns_mem_free(ns_mem_book_t *book, void *block) free(block); platform_exit_critical(); #endif + + mbed_ns_heap_free_hook(); } void ns_dyn_mem_free(void *block) diff --git a/connectivity/lwipstack/include/lwipstack/LWIPMemoryManager.h b/connectivity/lwipstack/include/lwipstack/LWIPMemoryManager.h index e3aae4c0bbf..64f4f4eddd3 100644 --- a/connectivity/lwipstack/include/lwipstack/LWIPMemoryManager.h +++ b/connectivity/lwipstack/include/lwipstack/LWIPMemoryManager.h @@ -19,151 +19,47 @@ #include "EMACMemoryManager.h" +// Hook called from LwIP whenever a pbuf chain containing at least one pool pbuf has been freed +extern "C" void mbed_lwip_on_pbuf_pool_free_hook(); class LWIPMemoryManager final : public EMACMemoryManager { public: - /** - * Allocates memory buffer from the heap - * - * Memory buffer allocated from heap is always contiguous and can be arbitrary size. - * - * @param size Size of the memory to allocate in bytes - * @param align Memory alignment requirement in bytes - * @return Allocated memory buffer, or NULL in case of error - */ net_stack_mem_buf_t *alloc_heap(uint32_t size, uint32_t align) override; - /** - * Allocates memory buffer chain from a pool - * - * Memory allocated from pool is contiguous if size is equal or less than - * (aligned) allocation unit, otherwise may be chained. Will typically come from - * fixed-size packet pool memory. - * - * @param size Total size of the memory to allocate in bytes - * @param align Memory alignment requirement for each buffer in bytes - * @return Allocated memory buffer chain, or NULL in case of error - */ net_stack_mem_buf_t *alloc_pool(uint32_t size, uint32_t align) override; - /** - * Get memory buffer pool allocation unit - * - * Returns the maximum size of contiguous memory that can be allocated from a pool. - * - * @param align Memory alignment requirement in bytes - * @return Contiguous memory size - */ uint32_t get_pool_alloc_unit(uint32_t align) const override; - /** - * Free memory buffer chain - * - * If memory buffer is chained must point to the start of the chain. Frees all buffers - * from the chained list. - * - * @param buf Memory buffer chain to be freed. - */ + uint32_t get_pool_size() const override; + void free(net_stack_mem_buf_t *buf) override; - /** - * Return total length of a memory buffer chain - * - * Returns a total length of this buffer and any following buffers in the chain. - * - * @param buf Memory buffer chain - * @return Total length in bytes - */ uint32_t get_total_len(const net_stack_mem_buf_t *buf) const override; - /** - * Copy a memory buffer chain - * - * Copies data from one buffer chain to another. Copy operation does not adjust the lengths - * of the copied-to memory buffer chain, so chain total lengths must be the same. - * - * @param to_buf Memory buffer chain to copy to - * @param from_buf Memory buffer chain to copy from - */ void copy(net_stack_mem_buf_t *to_buf, const net_stack_mem_buf_t *from_buf) override; - /** - * Copy to a memory buffer chain - * - * Copies data to a buffer chain. Copy operation does not adjust the lengths - * of the copied-to memory buffer chain, so chain total length must match the - * copied length. - * - * @param to_buf Memory buffer chain to copy to - * @param ptr Pointer to data - * @param len Data length - */ void copy_to_buf(net_stack_mem_buf_t *to_buf, const void *ptr, uint32_t len) override; - /** - * Copy from a memory buffer chain - * - * Copies data from a memory buffer chain. - * - * @param len Data length - * @param ptr Pointer to data - * @param from_buf Memory buffer chain to copy from - * @return Length of the data that was copied - */ uint32_t copy_from_buf(void *ptr, uint32_t len, const net_stack_mem_buf_t *from_buf) const override; - /** - * Concatenate two memory buffer chains - * - * Concatenates buffer chain to end of the other buffer chain. Concatenated-to buffer total length - * is adjusted accordingly. cat_buf must point to the start of a the chain. After concatenation - * to_buf's chain now owns those buffers, and they will be freed when the to_buf chain is freed. - * - * @param to_buf Memory buffer chain to concatenate to - * @param cat_buf Memory buffer chain to concatenate - */ void cat(net_stack_mem_buf_t *to_buf, net_stack_mem_buf_t *cat_buf) override; - /** - * Returns the next buffer - * - * Returns the next buffer from the memory buffer chain. - * - * @param buf Memory buffer - * @return The next memory buffer, or NULL if last - */ net_stack_mem_buf_t *get_next(const net_stack_mem_buf_t *buf) const override; - /** - * Return pointer to the payload of the buffer - * - * @param buf Memory buffer - * @return Pointer to the payload - */ void *get_ptr(const net_stack_mem_buf_t *buf) const override; - /** - * Return payload size of the buffer - * - * @param buf Memory buffer - * @return Size in bytes - */ uint32_t get_len(const net_stack_mem_buf_t *buf) const override; - /** - * Sets the payload size of the buffer - * - * The allocated payload size will not change. It is not permitted - * to change the length of a buffer that is not the first (or only) in a chain. - * - * @param buf Memory buffer - * @param len Payload size, must be less or equal allocated size - */ void set_len(net_stack_mem_buf_t *buf, uint32_t len) override; + Lifetime get_lifetime(const net_stack_mem_buf_t *buf) const override; + private: + // Allow callback to access private vars + friend void mbed_lwip_on_pbuf_pool_free_hook(); + /** * Returns a total memory alignment size * @@ -192,7 +88,7 @@ class LWIPMemoryManager final : public EMACMemoryManager { * Sets total lengths of a memory buffer chain * * Sets total length fields for a memory buffer chain based on buffer - * length fields. All total lengths are calculated again. + * \c len fields. All total lengths are calculated again. * * @param pbuf Memory buffer */ diff --git a/connectivity/lwipstack/include/lwipstack/LWIPStack.h b/connectivity/lwipstack/include/lwipstack/LWIPStack.h index 36550f0bd7f..b5cb88e248c 100644 --- a/connectivity/lwipstack/include/lwipstack/LWIPStack.h +++ b/connectivity/lwipstack/include/lwipstack/LWIPStack.h @@ -344,6 +344,12 @@ class LWIP : public OnboardNetworkStack, private mbed::NonCopyable { */ void set_default_interface(OnboardNetworkStack::Interface *interface) override; + /// Get the memory manager for the LwIP stack + LWIPMemoryManager &get_memory_manager() + { + return memory_manager; + } + protected: LWIP(); diff --git a/connectivity/lwipstack/include/lwipstack/lwipopts.h b/connectivity/lwipstack/include/lwipstack/lwipopts.h index b2e509dbfdd..9ed4c21087c 100644 --- a/connectivity/lwipstack/include/lwipstack/lwipopts.h +++ b/connectivity/lwipstack/include/lwipstack/lwipopts.h @@ -1,4 +1,5 @@ /* Copyright (C) 2012 mbed.org, MIT License + * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without restriction, @@ -136,11 +137,11 @@ // Number of pool pbufs. // Each requires 684 bytes of RAM (if MSS=536 and PBUF_POOL_BUFSIZE defaulting to be based on MSS) -#define PBUF_POOL_SIZE MBED_CONF_LWIP_PBUF_POOL_SIZE +#define PBUF_POOL_SIZE MBED_CONF_NSAPI_EMAC_RX_POOL_NUM_BUFS -#ifdef MBED_CONF_LWIP_PBUF_POOL_BUFSIZE +#ifdef MBED_CONF_NSAPI_EMAC_RX_POOL_BUF_SIZE #undef PBUF_POOL_BUFSIZE -#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_LWIP_PBUF_POOL_BUFSIZE) +#define PBUF_POOL_BUFSIZE LWIP_MEM_ALIGN_SIZE(MBED_CONF_NSAPI_EMAC_RX_POOL_BUF_SIZE) #else #ifndef PBUF_POOL_BUFSIZE #if LWIP_IPV6 diff --git a/connectivity/lwipstack/lwip-sys/arch/cc.h b/connectivity/lwipstack/lwip-sys/arch/cc.h index 8e46dd5eeb2..6234e80471f 100644 --- a/connectivity/lwipstack/lwip-sys/arch/cc.h +++ b/connectivity/lwipstack/lwip-sys/arch/cc.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2001-2003 Swedish Institute of Computer Science. * All rights reserved. + * SPDX-License-Identifier: BSD-3-Clause * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -136,7 +137,7 @@ void trace_to_ascii_hex_dump(char* prefix, int len, char *data); # elif defined(TOOLCHAIN_GCC_CR) # define MEMP_SECTION __attribute__((section(".data.$RamPeriph32"))) # else -# define MEMP_SECTION __attribute__((section("AHBSRAM1"),aligned)) +# define MEMP_SECTION __attribute__((section("AHBSRAM"),aligned)) # endif #endif #endif diff --git a/connectivity/lwipstack/lwip/src/core/lwip_pbuf.c b/connectivity/lwipstack/lwip/src/core/lwip_pbuf.c index a519c415687..1123041891b 100644 --- a/connectivity/lwipstack/lwip/src/core/lwip_pbuf.c +++ b/connectivity/lwipstack/lwip/src/core/lwip_pbuf.c @@ -1,6 +1,7 @@ /** * @file * Packet buffer management + * SPDX-License-Identifier: BSD-3-Clause */ /** @@ -739,6 +740,9 @@ pbuf_free(struct pbuf *p) PERF_START; count = 0; + + bool pbuf_pool_freed = false; + /* de-allocate all consecutive pbufs from the head of the chain that * obtain a zero reference count after decrementing*/ while (p != NULL) { @@ -771,6 +775,9 @@ pbuf_free(struct pbuf *p) /* is this a pbuf from the pool? */ if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) { memp_free(MEMP_PBUF_POOL, p); + + // Mbed OS Patch: set flag that buffer was from the pool + pbuf_pool_freed = true; /* is this a ROM or RAM referencing pbuf? */ } else if (alloc_src == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) { memp_free(MEMP_PBUF, p); @@ -793,6 +800,13 @@ pbuf_free(struct pbuf *p) p = NULL; } } + + // Mbed OS Patch: Hook into the memory manager when a POOL buffer is freed. + if(pbuf_pool_freed) { + extern void mbed_lwip_on_pbuf_pool_free_hook(void); + mbed_lwip_on_pbuf_pool_free_hook(); + } + PERF_STOP("pbuf_free"); /* return number of de-allocated pbufs */ return count; diff --git a/connectivity/lwipstack/mbed_lib.json b/connectivity/lwipstack/mbed_lib.json5 similarity index 87% rename from connectivity/lwipstack/mbed_lib.json rename to connectivity/lwipstack/mbed_lib.json5 index b39783b582a..5ea4a99ec98 100644 --- a/connectivity/lwipstack/mbed_lib.json +++ b/connectivity/lwipstack/mbed_lib.json5 @@ -118,14 +118,6 @@ "help": "Priority of lwip TCPIP thread", "value": "osPriorityNormal" }, - "pbuf-pool-size": { - "help": "Number of pbufs in pool - usually used for received packets, so this determines how much data can be buffered between reception and the application reading, see LWIP's opt.h for more information. If a driver uses PBUF_RAM for reception, less pool may be needed. Current default is 5.", - "value": 5 - }, - "pbuf-pool-bufsize": { - "help": "Size of pbufs in pool, see LWIP's opt.h for more information.", - "value": null - }, "mem-size": { "help": "Size of heap (bytes) - used for outgoing packets, and also used by some drivers for reception, see LWIP's opt.h for more information. Current default is 1600.", "value": 1600 @@ -189,34 +181,19 @@ "RZ_A1XX": { "tcpip-thread-stacksize": 1328, "default-thread-stacksize": 640, - "memp-num-tcp-seg": 32, - "tcp-mss": 1440, - "tcp-snd-buf": "(8 * TCP_MSS)", - "tcp-wnd": "(TCP_MSS * 8)", - "pbuf-pool-size": 16, "mem-size": 51200 }, "RZ_A2XX": { "tcpip-thread-stacksize": 1328, "default-thread-stacksize": 640, - "memp-num-tcp-seg": 32, - "tcp-mss": 1440, - "tcp-snd-buf": "(8 * TCP_MSS)", - "tcp-wnd": "(TCP_MSS * 8)", - "pbuf-pool-size": 16, "mem-size": 51200 }, "MCU_PSOC6": { "tcpip-thread-stacksize": 8192, "default-thread-stacksize": 640, - "memp-num-tcp-seg": 24, "tcp-socket-max": 10, "udp-socket-max":10, "socket-max":18, - "tcp-mss": 1540, - "tcp-snd-buf": "(6 * TCP_MSS)", - "tcp-wnd": "(TCP_MSS * 6)", - "pbuf-pool-size": 14, "mem-size": 65536 }, "MIMXRT105X": { diff --git a/connectivity/lwipstack/source/LWIPMemoryManager.cpp b/connectivity/lwipstack/source/LWIPMemoryManager.cpp index ae583743e99..ede74916329 100644 --- a/connectivity/lwipstack/source/LWIPMemoryManager.cpp +++ b/connectivity/lwipstack/source/LWIPMemoryManager.cpp @@ -17,6 +17,8 @@ #include "pbuf.h" #include "LWIPMemoryManager.h" +#include + net_stack_mem_buf_t *LWIPMemoryManager::alloc_heap(uint32_t size, uint32_t align) { struct pbuf *pbuf = pbuf_alloc(PBUF_RAW, size + align, PBUF_RAM); @@ -49,6 +51,11 @@ uint32_t LWIPMemoryManager::get_pool_alloc_unit(uint32_t align) const return alloc_unit; } +uint32_t LWIPMemoryManager::get_pool_size() const +{ + return PBUF_POOL_SIZE; +} + void LWIPMemoryManager::free(net_stack_mem_buf_t *buf) { pbuf_free(static_cast(buf)); @@ -105,6 +112,23 @@ void LWIPMemoryManager::set_len(net_stack_mem_buf_t *buf, uint32_t len) set_total_len(pbuf); } +NetStackMemoryManager::Lifetime LWIPMemoryManager::get_lifetime(const net_stack_mem_buf_t *buf) const +{ + auto const *p = static_cast(buf); + + uint8_t allocSrc = pbuf_get_allocsrc(p); + + if (allocSrc == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF && PBUF_NEEDS_COPY(p)) { + return Lifetime::VOLATILE; + } else if (allocSrc == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF) { + return Lifetime::CONSTANT; + } else if (allocSrc == PBUF_TYPE_ALLOC_SRC_MASK_STD_MEMP_PBUF_POOL) { + return Lifetime::POOL_ALLOCATED; + } else { + return Lifetime::HEAP_ALLOCATED; + } +} + uint32_t LWIPMemoryManager::count_total_align(uint32_t size, uint32_t align) { uint32_t buffers = size / get_pool_alloc_unit(align); @@ -162,3 +186,11 @@ void LWIPMemoryManager::set_total_len(struct pbuf *pbuf) pbuf = pbuf->next; } } + +void mbed_lwip_on_pbuf_pool_free_hook() +{ + auto &callback = LWIP::get_instance().get_memory_manager().onPoolSpaceAvailCallback; + if (callback) { + callback(); + } +} diff --git a/connectivity/lwipstack/source/LWIPStack.cpp b/connectivity/lwipstack/source/LWIPStack.cpp index 210b6e1b750..03234056818 100644 --- a/connectivity/lwipstack/source/LWIPStack.cpp +++ b/connectivity/lwipstack/source/LWIPStack.cpp @@ -550,6 +550,9 @@ nsapi_size_or_error_t LWIP::socket_sendto_control(nsapi_socket_t handle, const S struct netbuf *buf = netbuf_new(); + // Note: netbuf_ref() tells LwIP that it can reference the application-supplied buffer, + // but only until sendto() returns. If it has to hold onto the buffer until later + // (e.g. due to an ARP packet that needs to be sent first), it must copy it. err_t err = netbuf_ref(buf, data, (u16_t)size); if (err != ERR_OK) { netbuf_free(buf); diff --git a/connectivity/nanostack/include/nanostack-interface/Nanostack.h b/connectivity/nanostack/include/nanostack-interface/Nanostack.h index d3677e3be30..f0cb31dbd1d 100644 --- a/connectivity/nanostack/include/nanostack-interface/Nanostack.h +++ b/connectivity/nanostack/include/nanostack-interface/Nanostack.h @@ -53,268 +53,54 @@ class Nanostack : public OnboardNetworkStack, private mbed::NonCopyable func) override; struct nanostack_callback { diff --git a/connectivity/nanostack/mbed-mesh-api/mbed_lib.json b/connectivity/nanostack/mbed-mesh-api/mbed_lib.json index deba8150bb0..59db804a0c1 100644 --- a/connectivity/nanostack/mbed-mesh-api/mbed_lib.json +++ b/connectivity/nanostack/mbed-mesh-api/mbed_lib.json @@ -241,6 +241,9 @@ "target_overrides": { "KW41Z": { "mbed-mesh-api.heap-size": 14000 + }, + "LPC1768": { + "mbed-mesh-api.heap-size": 16383 } } } diff --git a/connectivity/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp b/connectivity/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp index c4a87df3d73..d903dacf41e 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp +++ b/connectivity/nanostack/mbed-mesh-api/source/NanostackEMACInterface.cpp @@ -122,7 +122,7 @@ int8_t EMACPhy::address_write(phy_address_type_e address_type, uint8_t *address_ int8_t EMACPhy::tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle, data_protocol_e data_flow) { - emac_mem_buf_t *mem = memory_manager.alloc_pool(data_len, 0); + emac_mem_buf_t *mem = memory_manager.alloc_heap(data_len, 0); if (!mem) { return -1; } diff --git a/connectivity/nanostack/mbed-mesh-api/source/NanostackMemoryManager.cpp b/connectivity/nanostack/mbed-mesh-api/source/NanostackMemoryManager.cpp index d87c6c18f62..1e2a71fe435 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/NanostackMemoryManager.cpp +++ b/connectivity/nanostack/mbed-mesh-api/source/NanostackMemoryManager.cpp @@ -19,6 +19,7 @@ #include #include "mbed_assert.h" #include "NanostackMemoryManager.h" +#include "NanostackEthernetInterface.h" struct ns_stack_mem_t { ns_stack_mem_t *next; @@ -55,12 +56,18 @@ emac_mem_buf_t *NanostackMemoryManager::alloc_heap(uint32_t size, uint32_t align emac_mem_buf_t *NanostackMemoryManager::alloc_pool(uint32_t size, uint32_t align) { + // Unlike LwIP, Nanostack does not treat pool buffers any differently from heap ones. return alloc_heap(size, align); } uint32_t NanostackMemoryManager::get_pool_alloc_unit(uint32_t align) const { - return 1536; // arbitrary nicely-aligned number big enough for Ethernet + return MBED_CONF_NSAPI_EMAC_RX_POOL_BUF_SIZE; +} + +uint32_t NanostackMemoryManager::get_pool_size() const +{ + return MBED_CONF_NSAPI_EMAC_RX_POOL_NUM_BUFS; } void NanostackMemoryManager::free(emac_mem_buf_t *mem) @@ -141,3 +148,18 @@ void NanostackMemoryManager::set_len(emac_mem_buf_t *buf, uint32_t len) mem->len = len; } + +NetStackMemoryManager::Lifetime NanostackMemoryManager::get_lifetime(const net_stack_mem_buf_t *buf) const +{ + // For Nanostack, all buffers are heap allocated and can be kept around as long as + // is needed by the EMAC driver. + return Lifetime::HEAP_ALLOCATED; +} + +void mbed_ns_heap_free_hook() +{ + auto &callback = Nanostack::get_instance().get_memory_manager().onPoolSpaceAvailCallback; + if (callback) { + callback(); + } +} diff --git a/connectivity/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp b/connectivity/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp index 5c9f8269655..3bd9df8f352 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp +++ b/connectivity/nanostack/mbed-mesh-api/source/NanostackPPPInterface.cpp @@ -250,7 +250,7 @@ int8_t PPPPhy::tx(uint8_t *data_ptr, uint16_t data_len, uint8_t tx_handle, data_ return -1; } - net_stack_mem_buf_t *mem = memory_manager.alloc_pool(data_len, 0); + net_stack_mem_buf_t *mem = memory_manager.alloc_heap(data_len, 0); if (!mem) { return -1; } diff --git a/connectivity/nanostack/mbed-mesh-api/source/include/NanostackMemoryManager.h b/connectivity/nanostack/mbed-mesh-api/source/include/NanostackMemoryManager.h index 947c38fd6eb..cd426b50909 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/include/NanostackMemoryManager.h +++ b/connectivity/nanostack/mbed-mesh-api/source/include/NanostackMemoryManager.h @@ -19,124 +19,41 @@ #include "EMACMemoryManager.h" +extern "C" void mbed_ns_heap_free_hook(); + class NanostackMemoryManager final : public EMACMemoryManager { + + // Allow the hook to call the callback from the superclass + friend void mbed_ns_heap_free_hook(); public: - /** - * Allocates memory buffer from the heap - * - * Memory buffer allocated from heap is always contiguous and can be arbitrary size. - * - * @param size Size of the memory to allocate in bytes - * @param align Memory alignment requirement in bytes - * @return Allocated memory buffer, or NULL in case of error - */ + virtual ~NanostackMemoryManager() = default; + emac_mem_buf_t *alloc_heap(uint32_t size, uint32_t align) override; - /** - * Allocates memory buffer chain from a pool - * - * Memory allocated from pool is contiguous if size is equal or less than - * (aligned) allocation unit, otherwise may be chained. Will typically come from - * fixed-size packet pool memory. - * - * @param size Total size of the memory to allocate in bytes - * @param align Memory alignment requirement for each buffer in bytes - * @return Allocated memory buffer chain, or NULL in case of error - */ emac_mem_buf_t *alloc_pool(uint32_t size, uint32_t align) override; - /** - * Get memory buffer pool allocation unit - * - * Returns the maximum size of contiguous memory that can be allocated from a pool. - * - * @param align Memory alignment requirement in bytes - * @return Contiguous memory size - */ uint32_t get_pool_alloc_unit(uint32_t align) const override; - /** - * Free memory buffer chain - * - * If memory buffer is chained must point to the start of the chain. Frees all buffers - * from the chained list. - * - * @param buf Memory buffer chain to be freed. - */ + uint32_t get_pool_size() const override; + void free(emac_mem_buf_t *buf) override; - /** - * Return total length of a memory buffer chain - * - * Returns a total length of this buffer and any following buffers in the chain. - * - * @param buf Memory buffer chain - * @return Total length in bytes - */ uint32_t get_total_len(const emac_mem_buf_t *buf) const override; - /** - * Copy a memory buffer chain - * - * Copies data from one buffer chain to another. Copy operation does not adjust the lengths - * of the copied-to memory buffer chain, so chain total lengths must be the same. - * - * @param to_buf Memory buffer chain to copy to - * @param from_buf Memory buffer chain to copy from - */ void copy(emac_mem_buf_t *to_buf, const emac_mem_buf_t *from_buf) override; - - - /** - * Concatenate two memory buffer chains - * - * Concatenates buffer chain to end of the other buffer chain. Concatenated-to buffer total length - * is adjusted accordingly. cat_buf must point to the start of a the chain. After concatenation - * to_buf's chain now owns those buffers, and they will be freed when the to_buf chain is freed. - * - * @param to_buf Memory buffer chain to concatenate to - * @param cat_buf Memory buffer chain to concatenate - */ void cat(emac_mem_buf_t *to_buf, emac_mem_buf_t *cat_buf) override; - /** - * Returns the next buffer - * - * Returns the next buffer from the memory buffer chain. - * - * @param buf Memory buffer - * @return The next memory buffer, or NULL if last - */ emac_mem_buf_t *get_next(const emac_mem_buf_t *buf) const override; - /** - * Return pointer to the payload of the buffer - * - * @param buf Memory buffer - * @return Pointer to the payload - */ void *get_ptr(const emac_mem_buf_t *buf) const override; - /** - * Return payload size of the buffer - * - * @param buf Memory buffer - * @return Size in bytes - */ uint32_t get_len(const emac_mem_buf_t *buf) const override; - /** - * Sets the payload size of the buffer - * - * The allocated payload size will not change. It is not permitted - * to change the length of a buffer that is not the first (or only) in a chain. - * - * @param buf Memory buffer - * @param len Payload size, must be less or equal allocated size - */ void set_len(emac_mem_buf_t *buf, uint32_t len) override; + + Lifetime get_lifetime(const net_stack_mem_buf_t *buf) const override; }; #endif /* NANOSTACK_MEMORY_MANAGER_H */ diff --git a/connectivity/nanostack/mbed-mesh-api/source/mesh_system.c b/connectivity/nanostack/mbed-mesh-api/source/mesh_system.c index 28bdabef084..9da50188173 100644 --- a/connectivity/nanostack/mbed-mesh-api/source/mesh_system.c +++ b/connectivity/nanostack/mbed-mesh-api/source/mesh_system.c @@ -32,9 +32,19 @@ #include "ns_trace.h" #define TRACE_GROUP "m6-mesh-system" +/* For LPC boards define the heap memory bank ourselves to give us section placement + control */ +#ifndef ETHMEM_SECTION +# if defined(TARGET_LPC1768) +# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned)) +# else +# define ETHMEM_SECTION +# endif +#endif + /* Heap for NanoStack */ #if !MBED_CONF_MBED_MESH_API_USE_MALLOC_FOR_HEAP -static uint8_t app_stack_heap[MBED_CONF_MBED_MESH_API_HEAP_SIZE + 1]; +ETHMEM_SECTION uint8_t app_stack_heap[MBED_CONF_MBED_MESH_API_HEAP_SIZE + 1]; #else static uint8_t *app_stack_heap; #endif diff --git a/connectivity/netsocket/include/netsocket/EMAC.h b/connectivity/netsocket/include/netsocket/EMAC.h index c018a0532eb..9adf83143d1 100644 --- a/connectivity/netsocket/include/netsocket/EMAC.h +++ b/connectivity/netsocket/include/netsocket/EMAC.h @@ -155,12 +155,18 @@ class EMAC { /** Add device to a multicast group * * @param address A multicast group hardware address + * + * @note The network stack will ensure that no two threads can call this function at + * the same time. It doesn't need locking at the MAC level. */ virtual void add_multicast_group(const uint8_t *address) = 0; /** Remove device from a multicast group * * @param address A multicast group hardware address + * + * @note The network stack will ensure that no two threads can call this function at + * the same time. It doesn't need locking at the MAC level. */ virtual void remove_multicast_group(const uint8_t *address) = 0; diff --git a/connectivity/netsocket/include/netsocket/NetStackMemoryManager.h b/connectivity/netsocket/include/netsocket/NetStackMemoryManager.h index e9596e05056..c58397b736f 100644 --- a/connectivity/netsocket/include/netsocket/NetStackMemoryManager.h +++ b/connectivity/netsocket/include/netsocket/NetStackMemoryManager.h @@ -21,17 +21,23 @@ /** * Network Stack interface memory manager * + * \par * This interface provides abstraction for memory modules used in different IP stacks (often to accommodate zero * copy). NetStack interface is required to accept output packets and provide received data using this stack- * independent API. This header should be implemented for each IP stack, so that we keep EMAC module independent. * + * \par * NetStack memory interface uses memory buffer chains to store data. Data passed in either direction - * may be either contiguous (a single-buffer chain), or may consist of multiple buffers. + * may either be contiguous (a single-buffer chain), or may consist of multiple buffers. * Chaining of the buffers is made using singly-linked list. The NetStack data-passing APIs do not specify * alignment or structure of the chain in either direction. * + * \par * Memory buffers can be allocated either from heap or from memory pools. Heap buffers are always contiguous. - * Memory pool buffers may be either contiguous or chained depending on allocation size. + * Memory pool buffers may be either contiguous or chained depending on allocation size. By LwIP convention, + * the pool should only be used for Rx packets -- the EMAC may opt to keep buffers pre-allocated from the pool + * for receiving packets into. This is done because LwIP will do special stuff when the pool runs out of space, + * e.g. flushing TCP out-of-sequence segment buffers to free up memory. * * On NetStack interface buffer chain ownership is transferred. EMAC must free buffer chain that it is given for * link output and the stack must free the buffer chain that it is given for link input. @@ -39,10 +45,22 @@ */ #include "nsapi.h" +#include "Callback.h" typedef void net_stack_mem_buf_t; // Memory buffer class NetStackMemoryManager { +protected: + /// Callback which shall be called (if set) by the implementation after one or more buffer spaces + /// become free in the pool. This is used by zero-copy Ethernet MACs as a hint that + /// now is a good time to allocate fresh buffers off the pool into Ethernet descriptors. + /// It *is* legal to call this function if you aren't totally sure new memory is available -- + /// the mac will try to allocate more buffers, and if it can't, oh well. + /// However, it is not legal for memory to become available without a call to this function. + /// Such a situation might lead to a lockup of the MAC due to not having memory allocated for Rx. + // TODO this eventually needs to get converted to a list once we support boards with more than 1 EMAC + mbed::Callback onPoolSpaceAvailCallback; + public: /** @@ -79,6 +97,13 @@ class NetStackMemoryManager { */ virtual uint32_t get_pool_alloc_unit(uint32_t align) const = 0; + /** + * Get memory buffer pool size. + * + * @return The maximum size of contiguous memory that can be allocated from a pool. + */ + virtual uint32_t get_pool_size() const = 0; + /** * Free memory buffer chain * @@ -156,6 +181,22 @@ class NetStackMemoryManager { */ virtual net_stack_mem_buf_t *get_next(const net_stack_mem_buf_t *buf) const = 0; + /** + * @brief Count the number of buffers in a buffer chain + * + * @param buf Memory buffer + * @return The number of buffers in the chain + */ + size_t count_buffers(const net_stack_mem_buf_t *buf) + { + size_t count = 0; + while (buf != nullptr) { + count += 1; + buf = get_next(buf); + } + return count; + } + /** * Return pointer to the payload of the buffer * @@ -165,7 +206,7 @@ class NetStackMemoryManager { virtual void *get_ptr(const net_stack_mem_buf_t *buf) const = 0; /** - * Return payload size of the buffer + * Return payload size of this individual buffer (NOT including any chained buffers) * * @param buf Memory buffer * @return Size in bytes @@ -178,11 +219,46 @@ class NetStackMemoryManager { * The allocated payload size will not change. It is not permitted * to change the length of a buffer that is not the first (or only) in a chain. * + * *Note as of Dec 2024: Different implementations (Nanostack vs LwIP) disagree about + * how to implement this operation. Specifically, if called on the head of a buffer + * chain, the LwIP implementation allows changing the length of the chain as a whole. + * However, the Nanostack implementation does not and only can change the length of the head buffer. + * For fear of breaking existing code, I do not want to change this behavior. + * So, if constructing a buffer chain, it is safest to set the buffer lengths first before + * building the chain. + * * @param buf Memory buffer * @param len Payload size, must be less or equal to the allocated size */ virtual void set_len(net_stack_mem_buf_t *buf, uint32_t len) = 0; + enum class Lifetime { + POOL_ALLOCATED, ///< Allocated from the memory manager's pool + HEAP_ALLOCATED, ///< Allocated from the memory manager's heap + CONSTANT, ///< Buffer points to constant data (e.g. in ROM) that will live forever + VOLATILE ///< Buffer points to data from the application that will not live past the current network stack call. + }; + + /** + * Gets the lifetime of the buffer + * + * @param buf Memory buffer + */ + virtual Lifetime get_lifetime(net_stack_mem_buf_t const *buf) const = 0; + + /** + * @brief Set callback which will be called when pool space becomes available + * + * \warning The callback could be called from any thread, and should make no assumptions about + * being in the same thread as anything else. + * + * @param cb Callback to call + */ + void set_on_pool_space_avail_cb(mbed::Callback cb) + { + onPoolSpaceAvailCallback = cb; + } + protected: ~NetStackMemoryManager() = default; }; diff --git a/connectivity/netsocket/mbed_lib.json b/connectivity/netsocket/mbed_lib.json5 similarity index 76% rename from connectivity/netsocket/mbed_lib.json rename to connectivity/netsocket/mbed_lib.json5 index d080275ba13..09041a195e8 100644 --- a/connectivity/netsocket/mbed_lib.json +++ b/connectivity/netsocket/mbed_lib.json5 @@ -77,6 +77,14 @@ "offload-tlssocket" : { "help": "Use external TLSSocket implementation. Used network stack must support external TLSSocket setsockopt values (see nsapi_types.h)", "value": null + }, + "emac-rx-pool-buf-size": { + "help": "Size of buffers in the EMAC receive pool. This determines the 'granularity' of allocations that are made for the Ethernet receive pool. Making this larger (up to the Ethernet MTU of 1536) will make receiving large packets more performant, but waste more buffer memory when receiving small packets.", + "value": 592 // LwIP default value (assuming default TCP MSS) + }, + "emac-rx-pool-num-bufs": { + "help": "Number of buffers (of size netsocket.emac-rx-pool-buf-size) in the EMAC receive pool. This controls how much memory is preallocated for Ethernet reception. A larger number means that more Ethernet packets can be received per second without dropping any. Some EMACs need up to 4 extra buffers, so this should be set such that this value minus 4 times the buffer size is at least 1514 (so we can receive one full Ethernet frame).", + "value": 7 } }, "target_overrides": { diff --git a/connectivity/netsocket/tests/TESTS/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/CMakeLists.txt index d269ac77908..1e8b234db06 100644 --- a/connectivity/netsocket/tests/TESTS/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/CMakeLists.txt @@ -5,24 +5,44 @@ if(DEFAULT_IFC_IDX EQUAL -1) set(TEST_SKIPPED "No default network interface on this target") endif() -# Set up variables for wi-fi SSID and password +# TEMPORARY: netsocket tests will not compile on STM32H7 until new EMAC driver is merged because the old EMAC driver +# pulls in a dependency on lwip +if("TARGET_STM32H7" IN_LIST MBED_TARGET_DEFINITIONS) + set(TEST_SKIPPED "Will not compile on STM32H7") +endif() + +add_subdirectory(common) + +# List of libraries for all netsocket tests to link. +# We have to be a bit careful here, because, in order to build tests with both lwip and nanostack, we have +# configured neither of the network stacks to provide the default implementation. +# Instead, the defaults are contained in the mbed-netsocket-tests-use-xxx libraries under common. +# Where we need to be careful is, any .a files that call OnboardNetworkStack::get_default_instance() need +# to appear BEFORE mbed-netsocket-tests-use-xxx on the link line, or you will get an undefined reference +# error. In CMake, there's no way to specify this kind of dependency except in the link line to the final +# executable. This means we need to list them out explicitly here. +set(MBED_NETSOCKET_TEST_COMMON_LIBS + mbed-netsocket-tests-common-inc) + +# Pull in cellular if cellular is the default network interface (used by NetworkInterfaceDefaults.cpp) +if("MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE=CELLULAR" IN_LIST MBED_CONFIG_DEFINITIONS) + list(APPEND MBED_NETSOCKET_TEST_COMMON_LIBS mbed-cellular) +endif() + +# Similarly if mesh networking is used bring in that library +if("MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE=MESH" IN_LIST MBED_CONFIG_DEFINITIONS) + list(APPEND MBED_NETSOCKET_TEST_COMMON_LIBS mbed-nanostack-mbed_mesh_api) +endif() + +# Similarly if wifi networking is used bring in that library if("MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE=WIFI" IN_LIST MBED_CONFIG_DEFINITIONS) - set(MBED_GREENTEA_WIFI_SECURE_SSID "" CACHE STRING "SSID of a secured wi-fi network with internet access, for greentea tests which need to connect to wifi") - set(MBED_GREENTEA_WIFI_SECURE_PASSWORD "" CACHE STRING "Password to the network given by MBED_GREENTEA_WIFI_SECURE_SSID") - set(MBED_GREENTEA_WIFI_SECURE_PROTOCOL "WPA2" CACHE STRING "WiFi security protocol, valid values are WEP, WPA, WPA2, WPA_WPA2, WPA3, WPA3_WPA2, NONE") - - if("${MBED_GREENTEA_WIFI_SECURE_SSID}" STREQUAL "" OR "${MBED_GREENTEA_WIFI_SECURE_PASSWORD}" STREQUAL "") - message(WARNING "MBED_GREENTEA_WIFI_SECURE_SSID and MBED_GREENTEA_WIFI_SECURE_PASSWORD must be set in order for wi-fi greentea tests to pass") - else() - add_compile_definitions( - "MBED_GREENTEA_WIFI_SECURE_SSID=\"${MBED_GREENTEA_WIFI_SECURE_SSID}\"" - "MBED_GREENTEA_WIFI_SECURE_PASSWORD=\"${MBED_GREENTEA_WIFI_SECURE_PASSWORD}\"" - MBED_GREENTEA_WIFI_SECURE_PROTOCOL=${MBED_GREENTEA_WIFI_SECURE_PROTOCOL}) - endif() + list(APPEND MBED_NETSOCKET_TEST_COMMON_LIBS mbed-wifi) endif() -# Pull in common util header -include_directories(common) +list(APPEND MBED_NETSOCKET_TEST_COMMON_LIBS mbed-netsocket-api) + +set(MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK ${MBED_NETSOCKET_TEST_COMMON_LIBS} mbed-netsocket-tests-use-lwipstack) +set(MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK ${MBED_NETSOCKET_TEST_COMMON_LIBS} mbed-netsocket-tests-use-nanostack) add_subdirectory(netsocket) add_subdirectory(network) \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/common/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/common/CMakeLists.txt new file mode 100644 index 00000000000..a2cb8961549 --- /dev/null +++ b/connectivity/netsocket/tests/TESTS/common/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2025 Jamie Smith. +# SPDX-License-Identifier: Apache-2.0 + +add_library(mbed-netsocket-tests-common-inc INTERFACE) +target_include_directories(mbed-netsocket-tests-common-inc INTERFACE .) +target_link_libraries(mbed-netsocket-tests-common-inc INTERFACE mbed-netsocket) + +# Set up variables for wi-fi SSID and password +if("MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE=WIFI" IN_LIST MBED_CONFIG_DEFINITIONS) + set(MBED_GREENTEA_WIFI_SECURE_SSID "" CACHE STRING "SSID of a secured wi-fi network with internet access, for greentea tests which need to connect to wifi") + set(MBED_GREENTEA_WIFI_SECURE_PASSWORD "" CACHE STRING "Password to the network given by MBED_GREENTEA_WIFI_SECURE_SSID") + set(MBED_GREENTEA_WIFI_SECURE_PROTOCOL "WPA2" CACHE STRING "WiFi security protocol, valid values are WEP, WPA, WPA2, WPA_WPA2, WPA3, WPA3_WPA2, NONE") + + if("${MBED_GREENTEA_WIFI_SECURE_SSID}" STREQUAL "" OR "${MBED_GREENTEA_WIFI_SECURE_PASSWORD}" STREQUAL "") + message(WARNING "MBED_GREENTEA_WIFI_SECURE_SSID and MBED_GREENTEA_WIFI_SECURE_PASSWORD must be set in order for wi-fi greentea tests to pass") + else() + target_compile_definitions(mbed-netsocket-tests-common-inc INTERFACE + "MBED_GREENTEA_WIFI_SECURE_SSID=\"${MBED_GREENTEA_WIFI_SECURE_SSID}\"" + "MBED_GREENTEA_WIFI_SECURE_PASSWORD=\"${MBED_GREENTEA_WIFI_SECURE_PASSWORD}\"" + MBED_GREENTEA_WIFI_SECURE_PROTOCOL=${MBED_GREENTEA_WIFI_SECURE_PROTOCOL}) + endif() +endif() + +# Tests can link one of the below two libraries to use lwipstack or nanostack +add_library(mbed-netsocket-tests-use-lwipstack STATIC EXCLUDE_FROM_ALL greentea_network_stack_lwipstack.cpp) +target_link_libraries(mbed-netsocket-tests-use-lwipstack PUBLIC mbed-lwipstack) + +add_library(mbed-netsocket-tests-use-nanostack STATIC EXCLUDE_FROM_ALL greentea_network_stack_nanostack.cpp) +target_link_libraries(mbed-netsocket-tests-use-nanostack PUBLIC mbed-nanostack) \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/common/greentea_get_network_interface.h b/connectivity/netsocket/tests/TESTS/common/greentea_get_network_interface.h index 9910640ea4a..ed55fca0c03 100644 --- a/connectivity/netsocket/tests/TESTS/common/greentea_get_network_interface.h +++ b/connectivity/netsocket/tests/TESTS/common/greentea_get_network_interface.h @@ -74,5 +74,4 @@ inline NetworkInterface *get_network_interface() #endif } - #endif //MBED_OS_GREENTEA_GET_NETWORK_INTERFACE_H diff --git a/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_lwipstack.cpp b/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_lwipstack.cpp new file mode 100644 index 00000000000..1fb11c4dd74 --- /dev/null +++ b/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_lwipstack.cpp @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2025 Jamie Smith, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "LWIPStack.h" +#include "OnboardNetworkStack.h" + +OnboardNetworkStack &OnboardNetworkStack::get_default_instance() +{ + return LWIP::get_instance(); +} diff --git a/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_nanostack.cpp b/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_nanostack.cpp new file mode 100644 index 00000000000..36547f05445 --- /dev/null +++ b/connectivity/netsocket/tests/TESTS/common/greentea_network_stack_nanostack.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Jamie Smith, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OnboardNetworkStack.h" +#include "Nanostack.h" + +OnboardNetworkStack &OnboardNetworkStack::get_default_instance() +{ + return Nanostack::get_instance(); +} + diff --git a/connectivity/netsocket/tests/TESTS/netsocket/dns/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/netsocket/dns/CMakeLists.txt index b8ad01b2a5b..1c209e9c030 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/dns/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/netsocket/dns/CMakeLists.txt @@ -23,17 +23,28 @@ list( asynchronous_dns_cache.cpp ) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "This test requires an RTOS!") endif() mbed_greentea_add_test( TEST_NAME - mbed-connectivity-netsocket-dns + mbed-connectivity-netsocket-lwipstack-dns TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) + +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-netsocket-nanostack-dns + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tcp/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/netsocket/tcp/CMakeLists.txt index dfb5f39d08d..0fa7be47c29 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tcp/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/netsocket/tcp/CMakeLists.txt @@ -27,17 +27,28 @@ list( tcpsocket_recv_100k.cpp ) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "This test requires an RTOS!") endif() mbed_greentea_add_test( TEST_NAME - mbed-connectivity-netsocket-tcp + mbed-connectivity-netsocket-lwipstack-tcp TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) + +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-netsocket-nanostack-tcp + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tls/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/netsocket/tls/CMakeLists.txt index b602f3e17af..c40089fa3b7 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tls/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/netsocket/tls/CMakeLists.txt @@ -23,7 +23,7 @@ list( tlssocket_cert_in_filesystem.cpp ) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "This test requires an RTOS!") endif() @@ -33,13 +33,26 @@ endif() mbed_greentea_add_test( TEST_NAME - mbed-connectivity-netsocket-tls + mbed-connectivity-netsocket-lwipstack-tls TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket mbed-storage-blockdevice - mbed-storage-littlefs + mbed-storage-littlefs + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) + +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-netsocket-nanostack-tls + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + mbed-storage-blockdevice + mbed-storage-littlefs + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/netsocket/udp/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/netsocket/udp/CMakeLists.txt index 8a9ac7bb45e..6b856513c49 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/udp/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/netsocket/udp/CMakeLists.txt @@ -23,17 +23,28 @@ list(APPEND udpsocket_echotest_burst.cpp ) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "This test requires an RTOS!") endif() mbed_greentea_add_test( TEST_NAME - mbed-connectivity-netsocket-udp + mbed-connectivity-netsocket-lwipstack-udp TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) + +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-netsocket-nanostack-udp + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) \ No newline at end of file diff --git a/connectivity/netsocket/tests/TESTS/network/emac/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/network/emac/CMakeLists.txt index 97503751ab8..cd4619cebae 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/network/emac/CMakeLists.txt @@ -26,8 +26,8 @@ mbed_greentea_add_test( TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket mbed-emac-test-utils + ${MBED_NETSOCKET_TEST_COMMON_LIBS} # We don't want LwIP or nanostack TEST_SKIPPED ${TEST_SKIPPED} ) diff --git a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_initialize.cpp b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_initialize.cpp index 5937e6aa3e6..5fe7b4535d1 100644 --- a/connectivity/netsocket/tests/TESTS/network/emac/emac_test_initialize.cpp +++ b/connectivity/netsocket/tests/TESTS/network/emac/emac_test_initialize.cpp @@ -17,6 +17,7 @@ #if defined(MBED_CONF_RTOS_PRESENT) #include "mbed.h" +#include "mbed_trace.h" #include "greentea-client/test_env.h" #include "unity.h" #include "utest.h" @@ -33,6 +34,11 @@ using namespace utest::v1; void test_emac_initialize() { worker_loop_init(); + mbed_trace_init(); + + // Set memory manager parameters + EmacTestMemoryManager::get_instance().set_alloc_unit(256); // Use a relatively small allocation unit size so packets have to be split up into a lot of buffers + EmacTestMemoryManager::get_instance().set_pool_size(10); // Start with 10 buffers in the Rx pool. One max-len Eth packet uses 6 256-byte buffers, and some MACs need up to 4 extra ones. static NetworkInterface *network_interface = get_network_interface(); diff --git a/connectivity/netsocket/tests/TESTS/network/interface/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/network/interface/CMakeLists.txt index 1eda04258e7..47fcc75289f 100644 --- a/connectivity/netsocket/tests/TESTS/network/interface/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/network/interface/CMakeLists.txt @@ -9,17 +9,29 @@ list( networkinterface_status.cpp ) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "This test requires an RTOS!") endif() mbed_greentea_add_test( TEST_NAME - mbed-connectivity-netsocket-network-interface + mbed-connectivity-netsocket-lwipstack-network-interface TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) + +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-netsocket-nanostack-network-interface + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) + diff --git a/connectivity/netsocket/tests/TESTS/network/wifi/CMakeLists.txt b/connectivity/netsocket/tests/TESTS/network/wifi/CMakeLists.txt index ba19268a034..0635bd7e74a 100644 --- a/connectivity/netsocket/tests/TESTS/network/wifi/CMakeLists.txt +++ b/connectivity/netsocket/tests/TESTS/network/wifi/CMakeLists.txt @@ -35,17 +35,30 @@ list( mbed_greentea_add_test( TEST_NAME - mbed-connectivity-network-wifi + mbed-connectivity-network-lwipstack-wifi TEST_SOURCES ${TEST_SOURCE_LIST} TEST_REQUIRED_LIBS - mbed-netsocket + ${MBED_NETSOCKET_TEST_COMMON_LIBS_LWIPSTACK} TEST_SKIPPED ${TEST_SKIPPED} ) -if(TARGET test-mbed-connectivity-network-wifi) - target_compile_definitions(test-mbed-connectivity-network-wifi PRIVATE - MBED_GREENTEA_WIFI_MAX_SCAN_SIZE=${MBED_GREENTEA_WIFI_MAX_SCAN_SIZE} - MBED_GREENTEA_WIFI_SECURE_CHANNEL=${MBED_GREENTEA_WIFI_SECURE_CHANNEL}) -endif() \ No newline at end of file +mbed_greentea_add_test( + TEST_NAME + mbed-connectivity-network-nanostack-wifi + TEST_SOURCES + ${TEST_SOURCE_LIST} + TEST_REQUIRED_LIBS + ${MBED_NETSOCKET_TEST_COMMON_LIBS_NANOSTACK} + TEST_SKIPPED + ${TEST_SKIPPED} +) + +foreach(TARGET test-mbed-connectivity-network-lwipstack-wifi test-mbed-connectivity-network-nanostack-wifi) + if(TARGET ${TARGET}) + target_compile_definitions(${TARGET} PRIVATE + MBED_GREENTEA_WIFI_MAX_SCAN_SIZE=${MBED_GREENTEA_WIFI_MAX_SCAN_SIZE} + MBED_GREENTEA_WIFI_SECURE_CHANNEL=${MBED_GREENTEA_WIFI_SECURE_CHANNEL}) + endif() +endforeach() \ No newline at end of file diff --git a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp index 858cdf6b259..bdbc26ff29e 100644 --- a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp @@ -36,8 +36,6 @@ #define CHECK_ASSERT(value, fmt, ...) check_value(value, fmt, ##__VA_ARGS__) -#define BUF_POOL_SIZE (14 + 40 + 20 + 536) /* Ethernet + IP + TCP + payload */ - #define MEM_MNGR_TRACE "test mem mngr: " char s_trace_buffer[100] = MEM_MNGR_TRACE; @@ -74,7 +72,8 @@ void emac_heap_error_handler(heap_fail_t event) EmacTestMemoryManager::EmacTestMemoryManager() : m_mem_mutex(), m_mem_buffers(), - m_alloc_unit(BUF_POOL_SIZE), + m_alloc_unit(MBED_CONF_NSAPI_EMAC_RX_POOL_BUF_SIZE), + m_pool_size(MBED_CONF_NSAPI_EMAC_RX_POOL_NUM_BUFS), m_memory_available(true) { #ifdef ETHMEM_SECTION @@ -123,6 +122,7 @@ emac_mem_buf_t *EmacTestMemoryManager::alloc_heap(uint32_t size, uint32_t align, buf->orig_len = size; buf->len = size; buf->first = true; + buf->lifetime = Lifetime::HEAP_ALLOCATED; if (opt & MEM_NO_ALIGN) { if (reinterpret_cast(buf->ptr) % sizeof(uint16_t) == 0) { @@ -145,6 +145,13 @@ emac_mem_buf_t *EmacTestMemoryManager::alloc_heap(uint32_t size, uint32_t align, char *buffer_tail = static_cast(buf->ptr) + buf->len; memcpy(buffer_tail, BUF_TAIL, BUF_TAIL_SIZE); + // Scribble over the buffer contents with 'y' so it's totally obvious if someone uses it uninitialized. + // Do this in both the cache and the main memory. + memset(buf->ptr, 'y', buf->orig_len); +#if __DCACHE_PRESENT + SCB_CleanDCache_by_Addr(buf->ptr, buf->orig_len); +#endif + m_mem_buffers.push_front(buf); m_mem_mutex.unlock(); @@ -169,9 +176,21 @@ emac_mem_buf_t *EmacTestMemoryManager::alloc_pool(uint32_t size, uint32_t align, return NULL; } + // Lock memory mutex + rtos::ScopedMutexLock lock(m_mem_mutex); + // Contiguous allocation if (size + align <= m_alloc_unit) { - return alloc_heap(size, align, opt); + if (m_pool_bufs_used > m_pool_size) { + return nullptr; + } + + auto *buf = alloc_heap(size, align, opt); + + static_cast(buf)->lifetime = Lifetime::POOL_ALLOCATED; + ++m_pool_bufs_used; + + return buf; } unsigned int pool_buffer_max_size = m_alloc_unit - align; @@ -195,8 +214,19 @@ emac_mem_buf_t *EmacTestMemoryManager::alloc_pool(uint32_t size, uint32_t align, size_left = 0; } + if (m_pool_bufs_used > m_pool_size) { + // No simulated pool space left, free and return nullptr + if (first_buf != nullptr) { + free(first_buf); + } + return nullptr; + } + emac_memory_t *new_buf = static_cast(alloc_heap(alloc_size, align, opt)); + static_cast(new_buf)->lifetime = Lifetime::POOL_ALLOCATED; + ++m_pool_bufs_used; + if (prev_buf) { new_buf->first = false; prev_buf->next = new_buf; @@ -232,6 +262,8 @@ void EmacTestMemoryManager::free(emac_mem_buf_t *buf) m_mem_mutex.lock(); + bool pool_buf_freed = false; + while (mem_buf) { for (mem_buf_entry = m_mem_buffers.begin(); mem_buf_entry != m_mem_buffers.end(); ++mem_buf_entry) { if (*mem_buf_entry == mem_buf) { @@ -255,6 +287,19 @@ void EmacTestMemoryManager::free(emac_mem_buf_t *buf) CHECK_ASSERT(0, "free(): %p tail overwrite", mem_buf); } + // Scribble over the buffer contents with 'z' so it's totally obvious if someone reuses it later. + // Do this in both the cache and the main memory. + memset(mem_buf->ptr, 'z', mem_buf->orig_len); +#if __DCACHE_PRESENT + SCB_CleanDCache_by_Addr(mem_buf->ptr, mem_buf->orig_len); +#endif + + // Update pool size + if (mem_buf->lifetime == Lifetime::POOL_ALLOCATED) { + --m_pool_bufs_used; + pool_buf_freed = true; + } + emac_memory_t *next = mem_buf->next; m_mem_buffers.erase(mem_buf_entry); @@ -270,6 +315,10 @@ void EmacTestMemoryManager::free(emac_mem_buf_t *buf) } m_mem_mutex.unlock(); + + if (pool_buf_freed && onPoolSpaceAvailCallback) { + onPoolSpaceAvailCallback(); + } } uint32_t EmacTestMemoryManager::get_total_len(const emac_mem_buf_t *buf) const @@ -437,6 +486,16 @@ void EmacTestMemoryManager::set_len(emac_mem_buf_t *buf, uint32_t len) mem_buf->len = len; } +uint32_t EmacTestMemoryManager::get_pool_size() const +{ + return m_pool_size; +} + +NetStackMemoryManager::Lifetime EmacTestMemoryManager::get_lifetime(const net_stack_mem_buf_t *buf) const +{ + return static_cast(buf)->lifetime; +} + void EmacTestMemoryManager::set_alloc_unit(uint32_t alloc_unit) { validate_list(); @@ -444,9 +503,19 @@ void EmacTestMemoryManager::set_alloc_unit(uint32_t alloc_unit) m_alloc_unit = alloc_unit; } +void EmacTestMemoryManager::set_pool_size(size_t size) +{ + m_pool_size = size; +} + void EmacTestMemoryManager::set_memory_available(bool memory) { m_memory_available = memory; + + // Poke the EMAC in case it can allocate buffers + if (m_memory_available && onPoolSpaceAvailCallback) { + onPoolSpaceAvailCallback(); + } } void EmacTestMemoryManager::get_memory_statistics(int *buffers, int *memory) @@ -542,4 +611,5 @@ EmacTestMemoryManager &EmacTestMemoryManager::get_instance() return test_memory_manager; } + #endif // defined(MBED_CONF_RTOS_PRESENT) diff --git a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.h b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.h index a63fef7e0ef..741a1b3b7a6 100644 --- a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.h +++ b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.h @@ -32,6 +32,7 @@ typedef struct emac_memory { unsigned int len; /**< Buffer length */ void *ptr; /**< Aligned pointer */ bool first; + EMACMemoryManager::Lifetime lifetime; } emac_memory_t; class EmacTestMemoryManager : public EMACMemoryManager { @@ -69,6 +70,10 @@ class EmacTestMemoryManager : public EMACMemoryManager { void set_len(emac_mem_buf_t *buf, uint32_t len) override; + uint32_t get_pool_size() const override; + + Lifetime get_lifetime(const net_stack_mem_buf_t *buf) const override; + /** * Allocates memory buffer from the heap * @@ -104,6 +109,16 @@ class EmacTestMemoryManager : public EMACMemoryManager { */ virtual void set_alloc_unit(uint32_t alloc_unit); + /** + * Sets memory buffer pool size + * + * Sets the number of buffers that may be allocated from the pool. If the number of buffers currently + * in use is >= this number, new pool allocations will fail. + * + * @param size Pool size + */ + virtual void set_pool_size(size_t size); + /** * Sets whether memory is available * @@ -131,6 +146,8 @@ class EmacTestMemoryManager : public EMACMemoryManager { mutable rtos::Mutex m_mem_mutex; std::list m_mem_buffers; unsigned int m_alloc_unit; + size_t m_pool_size; + size_t m_pool_bufs_used = 0; bool m_memory_available; }; diff --git a/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp b/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp index 1ac6ff58eac..550b8ba7046 100644 --- a/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/emac_util.cpp @@ -30,7 +30,7 @@ control */ #ifndef ETHMEM_SECTION #if defined(TARGET_LPC1768) -#define ETHMEM_SECTION __attribute__((section("AHBSRAM1"),aligned)) +#define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned)) #endif #endif diff --git a/drivers/tests/TESTS/mbed_drivers/lp_timeout/CMakeLists.txt b/drivers/tests/TESTS/mbed_drivers/lp_timeout/CMakeLists.txt index 564c42966ba..641f8cd395c 100644 --- a/drivers/tests/TESTS/mbed_drivers/lp_timeout/CMakeLists.txt +++ b/drivers/tests/TESTS/mbed_drivers/lp_timeout/CMakeLists.txt @@ -5,8 +5,8 @@ if(NOT "DEVICE_LPTICKER=1" IN_LIST MBED_TARGET_DEFINITIONS) set(TEST_SKIPPED "Low power ticker not supported for this target") endif() -if(MBED_GREENTEA_TEST_BAREMETAL) - set(TEST_SKIPPED "Low power timer not supported for this target") +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) + set(TEST_SKIPPED "Test not supported on baremetal") endif() mbed_greentea_add_test( diff --git a/drivers/tests/TESTS/mbed_drivers/race_test/CMakeLists.txt b/drivers/tests/TESTS/mbed_drivers/race_test/CMakeLists.txt index ccce698f811..403c6960e41 100644 --- a/drivers/tests/TESTS/mbed_drivers/race_test/CMakeLists.txt +++ b/drivers/tests/TESTS/mbed_drivers/race_test/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) 2020 ARM Limited. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "Mutex test cases require RTOS with multithread to run") endif() diff --git a/drivers/usb/tests/TESTS/usb_device/msd/CMakeLists.txt b/drivers/usb/tests/TESTS/usb_device/msd/CMakeLists.txt index 59a434af5cd..86d4a9e0d93 100644 --- a/drivers/usb/tests/TESTS/usb_device/msd/CMakeLists.txt +++ b/drivers/usb/tests/TESTS/usb_device/msd/CMakeLists.txt @@ -5,7 +5,7 @@ if(NOT "DEVICE_USBDEVICE=1" IN_LIST MBED_TARGET_DEFINITIONS) set(TEST_SKIPPED "USB Device is not supported for this target") endif() -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "USB MSD test is not compatible with mbed-baremetal") endif() diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/test/CMakeLists.txt b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/test/CMakeLists.txt index 6c3c9487b21..5b589e6bd2a 100644 --- a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/test/CMakeLists.txt +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/TESTS/attestation/test/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "RTOS required") endif() diff --git a/platform/include/platform/CacheAlignedBuffer.h b/platform/include/platform/CacheAlignedBuffer.h index 50b418b7de8..d0684c72441 100644 --- a/platform/include/platform/CacheAlignedBuffer.h +++ b/platform/include/platform/CacheAlignedBuffer.h @@ -275,7 +275,8 @@ class StaticCacheAlignedBuffer : public CacheAlignedBuffer { * * Use a DynamicCacheAlignedBuffer when you want to create a cache-aligned buffer with a size * known only at runtime. When constructed, %DynamicCacheAlignedBuffers allocate backing memory off the - * heap for the provided number of elements. The memory will be released when the buffer object is destroyed. + * heap for the provided number of elements, plus a little extra for alignment. The memory will be deleted when + * the buffer object is destroyed. * * @tparam DataT Type of the data to store in the buffer. Note: %CacheAlignedBuffer is not designed for * using class types as DataT, and will not call constructors. diff --git a/platform/mbed-trace/source/mbed_trace.c b/platform/mbed-trace/source/mbed_trace.c index 8a4897f31e0..6ab153cdeb2 100644 --- a/platform/mbed-trace/source/mbed_trace.c +++ b/platform/mbed-trace/source/mbed_trace.c @@ -304,7 +304,7 @@ static int8_t mbed_trace_skip(int8_t dlevel, const char *grp) if (m_trace.filters_include[0] != '\0' && strstr(m_trace.filters_include, grp) == 0) { //grp was in include list - return 1; + return 0; } } return 0; diff --git a/platform/tests/TESTS/mbed_platform/atomic/CMakeLists.txt b/platform/tests/TESTS/mbed_platform/atomic/CMakeLists.txt index c24a9dce663..941c3089d8d 100644 --- a/platform/tests/TESTS/mbed_platform/atomic/CMakeLists.txt +++ b/platform/tests/TESTS/mbed_platform/atomic/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "atomic test cases require a RTOS to run.") endif() diff --git a/rtos/include/rtos/Mutex.h b/rtos/include/rtos/Mutex.h index 553a430db86..6071bf697c9 100644 --- a/rtos/include/rtos/Mutex.h +++ b/rtos/include/rtos/Mutex.h @@ -55,17 +55,26 @@ typedef mbed::ScopedLock ScopedMutexLock; * @{ */ -/** The Mutex class is used to synchronize the execution of threads. - This is, for example, used to protect access to a shared resource. - - In bare-metal builds, the Mutex class is a dummy, so lock() and unlock() are no-ops. - - @note You cannot use member functions of this class in ISR context. If you require Mutex functionality within - ISR handler, consider using @a Semaphore. - - @note - Memory considerations: The mutex control structures are created on the current thread's stack, both for the Mbed OS - and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). +/** + * @brief The Mutex class is used to synchronize the execution of threads. + * + * \par + * This is, for example, used to protect access to a shared resource. + * + * \par + * In bare-metal builds, the Mutex class is a dummy, so lock() and unlock() are no-ops. + * + * \par + * Mbed Mutexes are recursive. So, if you call the \c lock() function multiple times, + * you must call \c unlock() the same number of times to unlock the mutex. This means that it's okay to lock + * a mutex, then call another function that also locks and unlocks the mutex, and the mutex won't actually + * get unlocked until your function unlocks it. + * + * @note You cannot use member functions of this class in ISR context. If you require Mutex functionality within ISR handler, consider using @a Semaphore. + * + * @note + * Memory considerations: The mutex control structures are created on the current thread's stack, both for the Mbed OS + * and underlying RTOS objects (static or dynamic RTOS memory pools are not being used). */ class Mutex : private mbed::NonCopyable { public: diff --git a/rtos/tests/TESTS/mbed_rtos/MemoryPool/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/MemoryPool/CMakeLists.txt index 3a163d578fd..bf7d757a978 100644 --- a/rtos/tests/TESTS/mbed_rtos/MemoryPool/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/MemoryPool/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(MBED_GREENTEA_TEST_BAREMETAL) +if(APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "MemoryPool test cases require a RTOS to run.") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/basic/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/basic/CMakeLists.txt index 394000ece71..27ae5722b81 100644 --- a/rtos/tests/TESTS/mbed_rtos/basic/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/basic/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "RTOS basic test cases require RTOS with multithread to run") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/condition_variable/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/condition_variable/CMakeLists.txt index 4ffb89017a5..e732a2997a6 100644 --- a/rtos/tests/TESTS/mbed_rtos/condition_variable/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/condition_variable/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "Condition variable test cases require RTOS with multithread to run") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/mail/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/mail/CMakeLists.txt index b311e2a06cd..4549790d68e 100644 --- a/rtos/tests/TESTS/mbed_rtos/mail/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/mail/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "mail test cases require RTOS with multithread to run") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/mutex/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/mutex/CMakeLists.txt index 0d123c9a6ea..e433887d674 100644 --- a/rtos/tests/TESTS/mbed_rtos/mutex/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/mutex/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "Mutex test cases require RTOS with multithread to run") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/queue/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/queue/CMakeLists.txt index a66628b0c25..05f7d44b551 100644 --- a/rtos/tests/TESTS/mbed_rtos/queue/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/queue/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "Queue test cases require RTOS with multithread to run") endif() diff --git a/rtos/tests/TESTS/mbed_rtos/threads/CMakeLists.txt b/rtos/tests/TESTS/mbed_rtos/threads/CMakeLists.txt index d40b9cf12c5..f24ac920e8f 100644 --- a/rtos/tests/TESTS/mbed_rtos/threads/CMakeLists.txt +++ b/rtos/tests/TESTS/mbed_rtos/threads/CMakeLists.txt @@ -3,7 +3,7 @@ include(mbed_greentea) -if(${MBED_C_LIB} STREQUAL "small" OR MBED_GREENTEA_TEST_BAREMETAL) +if(${MBED_C_LIB} STREQUAL "small" OR APPLICATION_PROFILE_CONFIG_BAREMETAL) set(TEST_SKIPPED "RTOS basic test cases require RTOS with multithread to run") endif() diff --git a/tools/test/ci/doxy-spellchecker/ignore.en.pws b/tools/test/ci/doxy-spellchecker/ignore.en.pws index c4bb36c1212..62f1613274c 100644 --- a/tools/test/ci/doxy-spellchecker/ignore.en.pws +++ b/tools/test/ci/doxy-spellchecker/ignore.en.pws @@ -132,3 +132,4 @@ MSBit LSBit busses STMicro +Nanostack