Skip to content

Commit

Permalink
LPC1768: Update linker script, support split heap (#430)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
multiplemonomials authored Jan 25, 2025
1 parent e712230 commit de95a07
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 65 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ cmake_install.cmake
CMakeFiles/
cmake_build/
Testing/
cmake-variants.yaml
CMakeUserPresets.json

# CLion
cmake-build-*/
2 changes: 1 addition & 1 deletion connectivity/lwipstack/lwip-sys/arch/lwip_sys_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::chrono::milliseconds>(timer.elapsed_time()).count());
}

void TCPSOCKET_RECV_100K()
Expand Down Expand Up @@ -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<std::chrono::milliseconds>(timer.elapsed_time()).count());
}

static void _sigio_handler(osThreadId id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 16 additions & 11 deletions drivers/tests/TESTS/mbed_drivers/flashiap/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<std::chrono::duration<float>>(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<std::chrono::duration<float>>(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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,36 @@
/* 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
#endif

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
Expand Down Expand Up @@ -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*)

Expand Down Expand Up @@ -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
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion targets/TARGET_NXP/TARGET_LPC176X/device/cmsis_nvic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
17 changes: 14 additions & 3 deletions targets/TARGET_NXP/TARGET_LPC176X/device/flash_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "cmsis.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

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

Expand Down Expand Up @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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
}

Expand Down
3 changes: 3 additions & 0 deletions targets/targets.json5
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit de95a07

Please sign in to comment.