diff --git a/.gitignore b/.gitignore index ca9d950d3f9..9300e0e3a37 100644 --- a/.gitignore +++ b/.gitignore @@ -103,6 +103,8 @@ cmake_install.cmake CMakeFiles/ cmake_build/ Testing/ +cmake-variants.yaml +CMakeUserPresets.json # CLion cmake-build-*/ \ No newline at end of file diff --git a/connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c b/connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c index 0d703cd928e..e8ac7a62108 100644 --- a/connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c +++ b/connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c @@ -37,7 +37,7 @@ # elif defined(TOOLCHAIN_GCC_CR) # define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) # else -# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned)) +# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned)) # endif #elif defined(TARGET_STM32H7) # if defined (__ICCARM__) diff --git a/connectivity/netsocket/tests/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp b/connectivity/netsocket/tests/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp index 1f503027c16..5d5a2af2583 100644 --- a/connectivity/netsocket/tests/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp +++ b/connectivity/netsocket/tests/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp @@ -117,7 +117,7 @@ void rcv_n_chk_against_rfc864_pattern(TCPSocket &sock) recvd_size += rd; } timer.stop(); - tr_info("MBED: Time taken: %fs", timer.read()); + tr_info("MBED: Time taken: %" PRIi64 "ms", std::chrono::duration_cast(timer.elapsed_time()).count()); } void TCPSOCKET_RECV_100K() @@ -172,7 +172,7 @@ void rcv_n_chk_against_rfc864_pattern_nonblock(TCPSocket &sock) } } timer.stop(); - tr_info("MBED: Time taken: %fs", timer.read()); + tr_info("MBED: Time taken: %" PRIi64 "ms", std::chrono::duration_cast(timer.elapsed_time()).count()); } static void _sigio_handler(osThreadId id) diff --git a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp index a8fe02a4bf8..858cdf6b259 100644 --- a/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp +++ b/connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp @@ -51,7 +51,7 @@ char s_trace_buffer[100] = MEM_MNGR_TRACE; # elif defined(TOOLCHAIN_GCC_CR) # define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32"))) # else -# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned)) +# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned)) # endif #endif #endif diff --git a/drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp b/drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp index 7b649155ba4..643f56670cd 100644 --- a/drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp +++ b/drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp @@ -249,11 +249,11 @@ void flashiap_timing_test() std::chrono::microseconds curr_time{}; std::chrono::microseconds avg_erase_time{}; unsigned int num_write_sizes; - unsigned int byte_usec_ratio; + float byte_sec_ratio; std::chrono::microseconds max_erase_time(0), min_erase_time(-1); const unsigned int max_writes = 128; const unsigned int max_write_sizes = 6; - const unsigned int max_byte_usec_ratio = 200; + const unsigned int max_byte_sec_ratio = 200000000; uint32_t page_size = flash_device.get_page_size(); uint32_t write_size = page_size; @@ -294,28 +294,33 @@ void flashiap_timing_test() } timer.reset(); ret = flash_device.program(buf, address, write_size); + + if (ret) { + printf("Failed programming %" PRIu32 " bytes at address 0x%" PRIx32 "\n!", write_size, address); + TEST_FAIL(); + } + curr_time = timer.elapsed_time(); avg_write_time += curr_time; - TEST_ASSERT_EQUAL_INT32(0, ret); max_write_time = us_max(max_write_time, curr_time); min_write_time = us_min(min_write_time, curr_time); address += write_size; } delete[] buf; avg_write_time /= num_writes; - byte_usec_ratio = write_size / avg_write_time.count(); - utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %10u bytes/usec\n", - write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_usec_ratio); - TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio); + byte_sec_ratio = write_size / std::chrono::duration_cast>(avg_write_time).count(); + utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %.01f bytes/sec\n", + write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_sec_ratio); + TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio); write_size *= 4; } if (num_write_sizes) { avg_erase_time /= num_write_sizes; - byte_usec_ratio = sector_size / avg_erase_time.count(); - utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %10u bytes/usec\n\n", - sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_usec_ratio); - TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio); + byte_sec_ratio = sector_size / std::chrono::duration_cast>(avg_erase_time).count(); + utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %.01f bytes/sec\n\n", + sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_sec_ratio); + TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio); } ret = flash_device.deinit(); diff --git a/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/LPC1768.ld b/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/LPC1768.ld index cf4492d079c..a97ed0719a4 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/LPC1768.ld +++ b/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/LPC1768.ld @@ -1,11 +1,21 @@ -/* Linker script for mbed LPC1768 */ -#if !defined(MBED_APP_START) - #define MBED_APP_START 0x00000000 -#endif - -#if !defined(MBED_APP_SIZE) - #define MBED_APP_SIZE 512K -#endif +/* mbed Microcontroller Library + * Copyright (c) 2025 Jamie Smith + * 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 "../cmsis_nvic.h" #if !defined(MBED_CONF_TARGET_BOOT_STACK_SIZE) #define MBED_CONF_TARGET_BOOT_STACK_SIZE 0x400 @@ -13,14 +23,14 @@ STACK_SIZE = MBED_CONF_TARGET_BOOT_STACK_SIZE; +#define VTORS_NEEDED_SPACE NVIC_NUM_VECTORS * 4 + /* Linker script to configure memory regions. */ MEMORY { - FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE - RAM (rwx) : ORIGIN = 0x100000C8, LENGTH = (32K - 0xC8 - 32) /* topmost 32 bytes used by IAP functions */ - - USB_RAM(rwx) : ORIGIN = 0x2007C000, LENGTH = 16K - ETH_RAM(rwx) : ORIGIN = 0x20080000, LENGTH = 16K + FLASH (rx) : ORIGIN = MBED_CONFIGURED_ROM_BANK_IROM1_START, LENGTH = MBED_CONFIGURED_ROM_BANK_IROM1_SIZE + RAM (rwx) : ORIGIN = MBED_RAM_BANK_IRAM1_START + VTORS_NEEDED_SPACE, LENGTH = (MBED_RAM_BANK_IRAM1_SIZE - VTORS_NEEDED_SPACE - 32) /* topmost 32 bytes used by IAP functions */ + AHBSRAM(rwx) : ORIGIN = MBED_RAM_BANK_IRAM2_START, LENGTH = MBED_RAM_BANK_IRAM2_SIZE } /* Linker script to place sections and symbol values. Should be used together @@ -56,9 +66,13 @@ SECTIONS .text : { KEEP(*(.isr_vector)) - /* Code Read Protect data */ + +#if MBED_CONFIGURED_ROM_BANK_IROM1_START == MBED_ROM_BANK_IROM1_START + /* Code Read Protect data, if this is at the start of flash*/ . = 0x000002FC ; KEEP(*(.CRPSection)) +#endif + /* End of Code Read Protect */ *(.text*) @@ -144,14 +158,13 @@ SECTIONS Image$$RW_IRAM1$$ZI$$Limit = . ; } > RAM - - .heap (NOLOAD): + .heap_0 (NOLOAD): ALIGN(8) { __end__ = .; end = __end__; - *(.heap*) - . = ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE; - __HeapLimit = .; + __mbed_sbrk_start_0 = .; + . = (ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE); + __mbed_krbs_start_0 = .; } > RAM /* .stack_dummy section doesn't contains any symbols. It is only @@ -169,24 +182,23 @@ SECTIONS PROVIDE(__stack = __StackTop); /* Check if data + heap + stack exceeds RAM limit */ - ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") + ASSERT(__StackLimit >= __end__, "region RAM overflowed with stack") /* Code can explicitly ask for data to be - placed in these higher RAM banks where + placed in this higher RAM bank where they will be left uninitialized. */ - .AHBSRAM0 (NOLOAD): + .AHBSRAM_bss (NOLOAD): { - Image$$RW_IRAM2$$Base = . ; - *(AHBSRAM0) - Image$$RW_IRAM2$$ZI$$Limit = .; - } > USB_RAM + *(AHBSRAM) + } > AHBSRAM - .AHBSRAM1 (NOLOAD): + /* Fill remaining space in AHBSRAM with additional heap */ + .heap (NOLOAD): ALIGN(8) { - Image$$RW_IRAM3$$Base = . ; - *(AHBSRAM1) - Image$$RW_IRAM3$$ZI$$Limit = .; - } > ETH_RAM + __mbed_sbrk_start = .; + . = ORIGIN(AHBSRAM) + LENGTH(AHBSRAM); + __mbed_krbs_start = .; + } > AHBSRAM } diff --git a/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/startup_LPC17xx.S b/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/startup_LPC17xx.S index fffc8954ee1..cef56a64ea2 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/startup_LPC17xx.S +++ b/targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/startup_LPC17xx.S @@ -30,21 +30,6 @@ aborting compilation, it is not the run time limit: Heap_Size + Stack_Size = 0x80 + 0x80 = 0x100 */ - - .section .heap - .align 3 -#ifdef __HEAP_SIZE - .equ Heap_Size, __HEAP_SIZE -#else - .equ Heap_Size, 0x800 -#endif - .globl __HeapBase - .globl __HeapLimit -__HeapBase: - .space Heap_Size - .size __HeapBase, . - __HeapBase -__HeapLimit: - .size __HeapLimit, . - __HeapLimit .section .isr_vector .align 2 diff --git a/targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h b/targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h index 2ea4323b43b..185a6436741 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h +++ b/targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h @@ -31,7 +31,7 @@ #ifndef MBED_CMSIS_NVIC_H #define MBED_CMSIS_NVIC_H -#define NVIC_NUM_VECTORS (16 + 33) +#define NVIC_NUM_VECTORS (16 + 35) #define NVIC_RAM_VECTOR_ADDRESS 0x10000000 // Location of vectors in RAM #endif diff --git a/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c b/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c index 259d420ec16..a75425993a4 100644 --- a/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c +++ b/targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c @@ -22,6 +22,8 @@ #include "cmsis.h" #include #include +#include +#include #define MEMMAP (*((volatile unsigned long *) 0x400FC040)) @@ -122,10 +124,18 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, // On LPC1768, the first RAM bank starts at 0x1000000, so anywhere below that has to be flash. // The IAP firmware does not support flash to flash copies, so if the source data is in flash // it must be buffered in RAM. - bool isFlashToFlashCopy = (ptrdiff_t)(data) < 0x10000000; + // Additionally, there seems to be an issue where the IAP ROM won't operate if a source page to be copied + // crosses the boundary between AHBSRAM0 and AHBSRAM1 + const bool startsInAHBSRAM1 = ((uint32_t)data) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START && ((uint32_t)data) < (MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384); + const bool endsInAHBSRAM2 = startsInAHBSRAM1 && ((((uint32_t)data) + size) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384); + const bool sourceAddressPageAligned = (((uint32_t)data) % pageSize) == 0; + bool mustBuffer = ((ptrdiff_t)(data) < MBED_CONFIGURED_RAM_BANK_IRAM1_START) || (startsInAHBSRAM1 && endsInAHBSRAM2 && !sourceAddressPageAligned); + + // printf("Flash program: flash address = 0x%" PRIx32 ", source data = 0x%" PRIx32 ", size = 0x%" PRIx32 ", startsInAHBSRAM1 = %d, endsInAHBSRAM2=%d, mustBuffer=%d\n", + // address, (ptrdiff_t)data, size, !!startsInAHBSRAM1, !!endsInAHBSRAM2, !!mustBuffer); // check word boundary - if (isFlashToFlashCopy) { + if (mustBuffer) { // always malloc outside critical section tempBuffer = malloc(pageSize); if (tempBuffer == 0) { @@ -140,7 +150,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, for(size_t pageIdx = 0; pageIdx < (size / pageSize); ++pageIdx) { uint8_t * pageSourceAddr = source + (pageIdx * pageSize); - if (isFlashToFlashCopy) { + if (mustBuffer) { memcpy(tempBuffer, pageSourceAddr, pageSize); pageSourceAddr = tempBuffer; } @@ -166,6 +176,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address, IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command if (IAP.stat) { core_util_critical_section_exit(); + //printf("IAP copy failed, address=0x%lx, pageSourceAddr=0x%lx, pageSize=%u\n", address, pageSourceAddr, pageSize); return -1; // Command Failed } diff --git a/targets/targets.json5 b/targets/targets.json5 index 6ace0dc27e8..02698f5b010 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -419,6 +419,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_toolchains": [ "GCC_ARM" ], + "macros": [ + "MBED_SPLIT_HEAP" + ], "device_has": [ "RTC", "USTICKER",