From 8225a8a7d01b7868b74a4e803b872405f9b4a87b Mon Sep 17 00:00:00 2001 From: Vladimir Smitka Date: Sun, 13 Sep 2026 20:55:58 +0000 Subject: [PATCH] nordic, stm, mimxrt10xx, analog: shrink property objects These ports never opted into CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE, so every read-only property carries two unused slots and every getter/setter pair one. Give the two sections a home in the linker script, the way atmel-samd and raspberrypi do, and turn the option on. The section bounds decide how many slots an object has, so a misplaced section would be read as a full property. The linker now asserts that each section is a whole number of objects. --- ports/analog/linking/max32690_cktpy.ld | 11 +++++++++++ ports/analog/mpconfigport.mk | 3 +++ ports/mimxrt10xx/linking/common.ld | 11 +++++++++++ ports/mimxrt10xx/mpconfigport.mk | 3 +++ ports/nordic/boards/common.template.ld | 11 +++++++++++ ports/nordic/mpconfigport.mk | 3 +++ ports/stm/boards/common_default.ld | 11 +++++++++++ ports/stm/boards/common_nvm.ld | 11 +++++++++++ ports/stm/boards/common_tcm.ld | 11 +++++++++++ ports/stm/mpconfigport.mk | 3 +++ 10 files changed, 78 insertions(+) diff --git a/ports/analog/linking/max32690_cktpy.ld b/ports/analog/linking/max32690_cktpy.ld index 9b32121a135..e802a8f9612 100644 --- a/ports/analog/linking/max32690_cktpy.ld +++ b/ports/analog/linking/max32690_cktpy.ld @@ -41,6 +41,12 @@ SECTIONS { .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; _text = .; /* ISR Vector beginning of .text */ @@ -183,4 +189,9 @@ SECTIONS { /* Check if data + heap + stack exceeds RAM limit */ ASSERT(__StackLimit >= _ebss, "region RAM overflowed with stack") + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/analog/mpconfigport.mk b/ports/analog/mpconfigport.mk index f1cd0bb2901..63521a27467 100644 --- a/ports/analog/mpconfigport.mk +++ b/ports/analog/mpconfigport.mk @@ -6,6 +6,9 @@ # # SPDX-License-Identifier: MIT +# Properties get a dedicated linker section here, so they can drop the unused slots. +CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 + CHIP_FAMILY ?= max32 # Necessary to build CircuitPython diff --git a/ports/mimxrt10xx/linking/common.ld b/ports/mimxrt10xx/linking/common.ld index 2c6be0dd129..1131f2b6f1f 100644 --- a/ports/mimxrt10xx/linking/common.ld +++ b/ports/mimxrt10xx/linking/common.ld @@ -69,6 +69,12 @@ SECTIONS .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; *(EXCLUDE_FILE( *fsl_flexspi.o *cd_ci_hs.o @@ -210,4 +216,9 @@ SECTIONS __StackTop = ORIGIN(DTCM) + LENGTH(DTCM); .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk index b3f078c7ecf..101568a8432 100644 --- a/ports/mimxrt10xx/mpconfigport.mk +++ b/ports/mimxrt10xx/mpconfigport.mk @@ -1,3 +1,6 @@ +# Properties get a dedicated linker section here, so they can drop the unused slots. +CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 + LD_FILE = $(FLASH).ld $(CHIP_FAMILY).ld imxrt10xx.ld INTERNAL_LIBM = 1 diff --git a/ports/nordic/boards/common.template.ld b/ports/nordic/boards/common.template.ld index dda31e4fdce..3828e3e7f9c 100644 --- a/ports/nordic/boards/common.template.ld +++ b/ports/nordic/boards/common.template.ld @@ -62,6 +62,12 @@ SECTIONS .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.text))) /* .text sections (code) */ *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.text*))) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ @@ -155,4 +161,9 @@ SECTIONS */ .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/nordic/mpconfigport.mk b/ports/nordic/mpconfigport.mk index a9299ee60aa..917bea89ff1 100644 --- a/ports/nordic/mpconfigport.mk +++ b/ports/nordic/mpconfigport.mk @@ -1,5 +1,8 @@ # All linking can be done with this common templated linker script, which has # parameters that vary based on chip and/or board. +# Properties get a dedicated linker section here, so they can drop the unused slots. +CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 + LD_TEMPLATE_FILE = boards/common.template.ld INTERNAL_LIBM = 1 diff --git a/ports/stm/boards/common_default.ld b/ports/stm/boards/common_default.ld index 7c96a42bc56..62a6d63d11c 100644 --- a/ports/stm/boards/common_default.ld +++ b/ports/stm/boards/common_default.ld @@ -35,6 +35,12 @@ SECTIONS .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ @@ -95,4 +101,9 @@ SECTIONS .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/stm/boards/common_nvm.ld b/ports/stm/boards/common_nvm.ld index 1d10db8a314..f2a0456e000 100644 --- a/ports/stm/boards/common_nvm.ld +++ b/ports/stm/boards/common_nvm.ld @@ -45,6 +45,12 @@ SECTIONS .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ @@ -105,4 +111,9 @@ SECTIONS .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/stm/boards/common_tcm.ld b/ports/stm/boards/common_tcm.ld index 6301dbf315b..18c284f965a 100644 --- a/ports/stm/boards/common_tcm.ld +++ b/ports/stm/boards/common_tcm.ld @@ -37,6 +37,12 @@ SECTIONS .text : { . = ALIGN(4); + __property_getter_start = .; + *(.property_getter) + __property_getter_end = .; + __property_getset_start = .; + *(.property_getset) + __property_getset_end = .; *(.text*) /* .text* sections (code) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ /* *(.glue_7) */ /* glue arm to thumb code */ @@ -146,4 +152,9 @@ SECTIONS } >FLASH_FIRMWARE .ARM.attributes 0 : { *(.ARM.attributes) } + + ASSERT((__property_getter_end - __property_getter_start) % 8 == 0, + "the .property_getter section must hold whole 8-byte objects") + ASSERT((__property_getset_end - __property_getset_start) % 12 == 0, + "the .property_getset section must hold whole 12-byte objects") } diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index bd2b2238eef..7ebdb1469ad 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -1,3 +1,6 @@ +# Properties get a dedicated linker section here, so they can drop the unused slots. +CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 + LONGINT_IMPL ?= MPZ INTERNAL_LIBM ?= 1