Skip to content

Commit de95a07

Browse files
author
Jamie Smith
authored
LPC1768: Update linker script, support split heap (#430)
* LPC1768: Update linker script, support split heap * Reclaim even more space if Ethernet is not used * Fix assert * Let's not assign absolute addresses to . * Revert "Let's not assign absolute addresses to ." This reverts commit 421fe70. * aha! Remove offending ASM code * Fix FlashIAP test failure * Style
1 parent e712230 commit de95a07

File tree

10 files changed

+83
-65
lines changed

10 files changed

+83
-65
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ cmake_install.cmake
103103
CMakeFiles/
104104
cmake_build/
105105
Testing/
106+
cmake-variants.yaml
107+
CMakeUserPresets.json
106108

107109
# CLion
108110
cmake-build-*/

connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
# elif defined(TOOLCHAIN_GCC_CR)
3838
# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
3939
# else
40-
# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
40+
# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned))
4141
# endif
4242
#elif defined(TARGET_STM32H7)
4343
# if defined (__ICCARM__)

connectivity/netsocket/tests/TESTS/netsocket/tcp/tcpsocket_recv_100k.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void rcv_n_chk_against_rfc864_pattern(TCPSocket &sock)
117117
recvd_size += rd;
118118
}
119119
timer.stop();
120-
tr_info("MBED: Time taken: %fs", timer.read());
120+
tr_info("MBED: Time taken: %" PRIi64 "ms", std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count());
121121
}
122122

123123
void TCPSOCKET_RECV_100K()
@@ -172,7 +172,7 @@ void rcv_n_chk_against_rfc864_pattern_nonblock(TCPSocket &sock)
172172
}
173173
}
174174
timer.stop();
175-
tr_info("MBED: Time taken: %fs", timer.read());
175+
tr_info("MBED: Time taken: %" PRIi64 "ms", std::chrono::duration_cast<std::chrono::milliseconds>(timer.elapsed_time()).count());
176176
}
177177

178178
static void _sigio_handler(osThreadId id)

connectivity/netsocket/tests/emac_test_utils/EmacTestMemoryManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ char s_trace_buffer[100] = MEM_MNGR_TRACE;
5151
# elif defined(TOOLCHAIN_GCC_CR)
5252
# define ETHMEM_SECTION __attribute__((section(".data.$RamPeriph32")))
5353
# else
54-
# define ETHMEM_SECTION __attribute__((section("AHBSRAM0"),aligned))
54+
# define ETHMEM_SECTION __attribute__((section("AHBSRAM"),aligned))
5555
# endif
5656
#endif
5757
#endif

drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,11 @@ void flashiap_timing_test()
249249
std::chrono::microseconds curr_time{};
250250
std::chrono::microseconds avg_erase_time{};
251251
unsigned int num_write_sizes;
252-
unsigned int byte_usec_ratio;
252+
float byte_sec_ratio;
253253
std::chrono::microseconds max_erase_time(0), min_erase_time(-1);
254254
const unsigned int max_writes = 128;
255255
const unsigned int max_write_sizes = 6;
256-
const unsigned int max_byte_usec_ratio = 200;
256+
const unsigned int max_byte_sec_ratio = 200000000;
257257

258258
uint32_t page_size = flash_device.get_page_size();
259259
uint32_t write_size = page_size;
@@ -294,28 +294,33 @@ void flashiap_timing_test()
294294
}
295295
timer.reset();
296296
ret = flash_device.program(buf, address, write_size);
297+
298+
if (ret) {
299+
printf("Failed programming %" PRIu32 " bytes at address 0x%" PRIx32 "\n!", write_size, address);
300+
TEST_FAIL();
301+
}
302+
297303
curr_time = timer.elapsed_time();
298304
avg_write_time += curr_time;
299-
TEST_ASSERT_EQUAL_INT32(0, ret);
300305
max_write_time = us_max(max_write_time, curr_time);
301306
min_write_time = us_min(min_write_time, curr_time);
302307
address += write_size;
303308
}
304309
delete[] buf;
305310
avg_write_time /= num_writes;
306-
byte_usec_ratio = write_size / avg_write_time.count();
307-
utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %10u bytes/usec\n",
308-
write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_usec_ratio);
309-
TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio);
311+
byte_sec_ratio = write_size / std::chrono::duration_cast<std::chrono::duration<float>>(avg_write_time).count();
312+
utest_printf("Write size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64 " (usec), rate %.01f bytes/sec\n",
313+
write_size, avg_write_time.count(), min_write_time.count(), max_write_time.count(), byte_sec_ratio);
314+
TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio);
310315
write_size *= 4;
311316
}
312317

313318
if (num_write_sizes) {
314319
avg_erase_time /= num_write_sizes;
315-
byte_usec_ratio = sector_size / avg_erase_time.count();
316-
utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %10u bytes/usec\n\n",
317-
sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_usec_ratio);
318-
TEST_ASSERT(byte_usec_ratio < max_byte_usec_ratio);
320+
byte_sec_ratio = sector_size / std::chrono::duration_cast<std::chrono::duration<float>>(avg_erase_time).count();
321+
utest_printf("\nErase size %6u bytes: avg %10" PRIi64 ", min %10" PRIi64 ", max %10" PRIi64" (usec), rate %.01f bytes/sec\n\n",
322+
sector_size, avg_erase_time.count(), min_erase_time.count(), max_erase_time.count(), byte_sec_ratio);
323+
TEST_ASSERT(byte_sec_ratio < max_byte_sec_ratio);
319324
}
320325

321326
ret = flash_device.deinit();

targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/LPC1768.ld

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,36 @@
1-
/* Linker script for mbed LPC1768 */
2-
#if !defined(MBED_APP_START)
3-
#define MBED_APP_START 0x00000000
4-
#endif
5-
6-
#if !defined(MBED_APP_SIZE)
7-
#define MBED_APP_SIZE 512K
8-
#endif
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2025 Jamie Smith
3+
* SPDX-License-Identifier: Apache-2.0
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "../cmsis_nvic.h"
919

1020
#if !defined(MBED_CONF_TARGET_BOOT_STACK_SIZE)
1121
#define MBED_CONF_TARGET_BOOT_STACK_SIZE 0x400
1222
#endif
1323

1424
STACK_SIZE = MBED_CONF_TARGET_BOOT_STACK_SIZE;
1525

26+
#define VTORS_NEEDED_SPACE NVIC_NUM_VECTORS * 4
27+
1628
/* Linker script to configure memory regions. */
1729
MEMORY
1830
{
19-
FLASH (rx) : ORIGIN = MBED_APP_START, LENGTH = MBED_APP_SIZE
20-
RAM (rwx) : ORIGIN = 0x100000C8, LENGTH = (32K - 0xC8 - 32) /* topmost 32 bytes used by IAP functions */
21-
22-
USB_RAM(rwx) : ORIGIN = 0x2007C000, LENGTH = 16K
23-
ETH_RAM(rwx) : ORIGIN = 0x20080000, LENGTH = 16K
31+
FLASH (rx) : ORIGIN = MBED_CONFIGURED_ROM_BANK_IROM1_START, LENGTH = MBED_CONFIGURED_ROM_BANK_IROM1_SIZE
32+
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 */
33+
AHBSRAM(rwx) : ORIGIN = MBED_RAM_BANK_IRAM2_START, LENGTH = MBED_RAM_BANK_IRAM2_SIZE
2434
}
2535

2636
/* Linker script to place sections and symbol values. Should be used together
@@ -56,9 +66,13 @@ SECTIONS
5666
.text :
5767
{
5868
KEEP(*(.isr_vector))
59-
/* Code Read Protect data */
69+
70+
#if MBED_CONFIGURED_ROM_BANK_IROM1_START == MBED_ROM_BANK_IROM1_START
71+
/* Code Read Protect data, if this is at the start of flash*/
6072
. = 0x000002FC ;
6173
KEEP(*(.CRPSection))
74+
#endif
75+
6276
/* End of Code Read Protect */
6377
*(.text*)
6478

@@ -144,14 +158,13 @@ SECTIONS
144158
Image$$RW_IRAM1$$ZI$$Limit = . ;
145159
} > RAM
146160

147-
148-
.heap (NOLOAD):
161+
.heap_0 (NOLOAD): ALIGN(8)
149162
{
150163
__end__ = .;
151164
end = __end__;
152-
*(.heap*)
153-
. = ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE;
154-
__HeapLimit = .;
165+
__mbed_sbrk_start_0 = .;
166+
. = (ORIGIN(RAM) + LENGTH(RAM) - STACK_SIZE);
167+
__mbed_krbs_start_0 = .;
155168
} > RAM
156169

157170
/* .stack_dummy section doesn't contains any symbols. It is only
@@ -169,24 +182,23 @@ SECTIONS
169182
PROVIDE(__stack = __StackTop);
170183

171184
/* Check if data + heap + stack exceeds RAM limit */
172-
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
185+
ASSERT(__StackLimit >= __end__, "region RAM overflowed with stack")
173186

174187

175188
/* Code can explicitly ask for data to be
176-
placed in these higher RAM banks where
189+
placed in this higher RAM bank where
177190
they will be left uninitialized.
178191
*/
179-
.AHBSRAM0 (NOLOAD):
192+
.AHBSRAM_bss (NOLOAD):
180193
{
181-
Image$$RW_IRAM2$$Base = . ;
182-
*(AHBSRAM0)
183-
Image$$RW_IRAM2$$ZI$$Limit = .;
184-
} > USB_RAM
194+
*(AHBSRAM)
195+
} > AHBSRAM
185196

186-
.AHBSRAM1 (NOLOAD):
197+
/* Fill remaining space in AHBSRAM with additional heap */
198+
.heap (NOLOAD): ALIGN(8)
187199
{
188-
Image$$RW_IRAM3$$Base = . ;
189-
*(AHBSRAM1)
190-
Image$$RW_IRAM3$$ZI$$Limit = .;
191-
} > ETH_RAM
200+
__mbed_sbrk_start = .;
201+
. = ORIGIN(AHBSRAM) + LENGTH(AHBSRAM);
202+
__mbed_krbs_start = .;
203+
} > AHBSRAM
192204
}

targets/TARGET_NXP/TARGET_LPC176X/device/TOOLCHAIN_GCC_ARM/startup_LPC17xx.S

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,6 @@
3030
aborting compilation, it is not the run time limit:
3131
Heap_Size + Stack_Size = 0x80 + 0x80 = 0x100
3232
*/
33-
34-
.section .heap
35-
.align 3
36-
#ifdef __HEAP_SIZE
37-
.equ Heap_Size, __HEAP_SIZE
38-
#else
39-
.equ Heap_Size, 0x800
40-
#endif
41-
.globl __HeapBase
42-
.globl __HeapLimit
43-
__HeapBase:
44-
.space Heap_Size
45-
.size __HeapBase, . - __HeapBase
46-
__HeapLimit:
47-
.size __HeapLimit, . - __HeapLimit
4833

4934
.section .isr_vector
5035
.align 2

targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#ifndef MBED_CMSIS_NVIC_H
3232
#define MBED_CMSIS_NVIC_H
3333

34-
#define NVIC_NUM_VECTORS (16 + 33)
34+
#define NVIC_NUM_VECTORS (16 + 35)
3535
#define NVIC_RAM_VECTOR_ADDRESS 0x10000000 // Location of vectors in RAM
3636

3737
#endif

targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include "cmsis.h"
2323
#include <stdlib.h>
2424
#include <string.h>
25+
#include <stdio.h>
26+
#include <inttypes.h>
2527

2628
#define MEMMAP (*((volatile unsigned long *) 0x400FC040))
2729

@@ -122,10 +124,18 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
122124
// On LPC1768, the first RAM bank starts at 0x1000000, so anywhere below that has to be flash.
123125
// The IAP firmware does not support flash to flash copies, so if the source data is in flash
124126
// it must be buffered in RAM.
125-
bool isFlashToFlashCopy = (ptrdiff_t)(data) < 0x10000000;
127+
// Additionally, there seems to be an issue where the IAP ROM won't operate if a source page to be copied
128+
// crosses the boundary between AHBSRAM0 and AHBSRAM1
129+
const bool startsInAHBSRAM1 = ((uint32_t)data) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START && ((uint32_t)data) < (MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384);
130+
const bool endsInAHBSRAM2 = startsInAHBSRAM1 && ((((uint32_t)data) + size) >= MBED_CONFIGURED_RAM_BANK_IRAM2_START + 16384);
131+
const bool sourceAddressPageAligned = (((uint32_t)data) % pageSize) == 0;
132+
bool mustBuffer = ((ptrdiff_t)(data) < MBED_CONFIGURED_RAM_BANK_IRAM1_START) || (startsInAHBSRAM1 && endsInAHBSRAM2 && !sourceAddressPageAligned);
133+
134+
// printf("Flash program: flash address = 0x%" PRIx32 ", source data = 0x%" PRIx32 ", size = 0x%" PRIx32 ", startsInAHBSRAM1 = %d, endsInAHBSRAM2=%d, mustBuffer=%d\n",
135+
// address, (ptrdiff_t)data, size, !!startsInAHBSRAM1, !!endsInAHBSRAM2, !!mustBuffer);
126136

127137
// check word boundary
128-
if (isFlashToFlashCopy) {
138+
if (mustBuffer) {
129139
// always malloc outside critical section
130140
tempBuffer = malloc(pageSize);
131141
if (tempBuffer == 0) {
@@ -140,7 +150,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
140150
for(size_t pageIdx = 0; pageIdx < (size / pageSize); ++pageIdx)
141151
{
142152
uint8_t * pageSourceAddr = source + (pageIdx * pageSize);
143-
if (isFlashToFlashCopy) {
153+
if (mustBuffer) {
144154
memcpy(tempBuffer, pageSourceAddr, pageSize);
145155
pageSourceAddr = tempBuffer;
146156
}
@@ -166,6 +176,7 @@ int32_t flash_program_page(flash_t *obj, uint32_t address,
166176
IAP_Call (&IAP.cmd, &IAP.stat); // Call IAP Command
167177
if (IAP.stat) {
168178
core_util_critical_section_exit();
179+
//printf("IAP copy failed, address=0x%lx, pageSourceAddr=0x%lx, pageSize=%u\n", address, pageSourceAddr, pageSize);
169180
return -1; // Command Failed
170181
}
171182

targets/targets.json5

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.",
419419
"supported_toolchains": [
420420
"GCC_ARM"
421421
],
422+
"macros": [
423+
"MBED_SPLIT_HEAP"
424+
],
422425
"device_has": [
423426
"RTC",
424427
"USTICKER",

0 commit comments

Comments
 (0)