diff --git a/arch/Kconfig b/arch/Kconfig index 916351ae605..f17c29ec6e3 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -33,6 +33,7 @@ config ARM select ARCH_IS_SET select ARCH_SUPPORTS_COREDUMP if CPU_CORTEX_M select ARCH_SUPPORTS_COREDUMP_THREADS if CPU_CORTEX_M + select ARCH_SUPPORTS_COREDUMP_STACK_PTR if CPU_CORTEX_M # FIXME: current state of the code for all ARM requires this, but # is really only necessary for Cortex-M with ARM MPU! select GEN_PRIV_STACKS @@ -695,6 +696,9 @@ config ARCH_SUPPORTS_COREDUMP_THREADS config ARCH_SUPPORTS_COREDUMP_PRIV_STACKS bool +config ARCH_SUPPORTS_COREDUMP_STACK_PTR + bool + config ARCH_SUPPORTS_ARCH_HW_INIT bool diff --git a/arch/arm/core/cortex_m/coredump.c b/arch/arm/core/cortex_m/coredump.c index ddb539c4e34..787cfcdf4a7 100644 --- a/arch/arm/core/cortex_m/coredump.c +++ b/arch/arm/core/cortex_m/coredump.c @@ -6,6 +6,7 @@ #include #include +#include #define ARCH_HDR_VER 2 @@ -96,3 +97,8 @@ uint16_t arch_coredump_tgt_code_get(void) { return COREDUMP_TGT_ARM_CORTEX_M; } + +uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread) +{ + return (thread == _current) ? z_arm_coredump_fault_sp : thread->callee_saved.psp; +} diff --git a/doc/releases/release-notes-4.2.rst b/doc/releases/release-notes-4.2.rst index 0514cf8a77d..bbd2bfda50b 100644 --- a/doc/releases/release-notes-4.2.rst +++ b/doc/releases/release-notes-4.2.rst @@ -212,6 +212,16 @@ New APIs and options * :kconfig:option:`CONFIG_NVME_PRP_PAGE_SIZE` +* Debug + + * Core Dump + + * :kconfig:option:`CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP`, enabled by default for ARM Cortex M when :kconfig:option:`CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN` is selected. + +* Other + + * :kconfig:option:`CONFIG_LV_Z_COLOR_MONO_HW_INVERSION` + New Boards ********** diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 05629c26a5f..956856a2ffc 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -638,6 +638,11 @@ void arch_coredump_info_dump(const struct arch_esf *esf); */ uint16_t arch_coredump_tgt_code_get(void); +/** + * @brief Get the stack pointer of the thread. + */ +uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread); + #if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__) /** diff --git a/lib/hash/hash_func32_murmur3.c b/lib/hash/hash_func32_murmur3.c index ff347c982f3..fa758354752 100644 --- a/lib/hash/hash_func32_murmur3.c +++ b/lib/hash/hash_func32_murmur3.c @@ -6,6 +6,8 @@ #include #include +#include +#include static inline uint32_t murmur_32_scramble(uint32_t k) { @@ -16,6 +18,14 @@ static inline uint32_t murmur_32_scramble(uint32_t k) return k; } +#define _LOOP(_GET) \ + for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) { \ + k = _GET; \ + h ^= murmur_32_scramble(k); \ + h = (h << 13) | (h >> 19); \ + h = h * 5 + 0xe6546b64; \ + } + uint32_t sys_hash32_murmur3(const char *str, size_t n) { uint32_t k; @@ -23,11 +33,10 @@ uint32_t sys_hash32_murmur3(const char *str, size_t n) uint32_t h = 0; const size_t len = n; - for (; n >= sizeof(uint32_t); n -= sizeof(uint32_t), str += sizeof(uint32_t)) { - k = *(const uint32_t *)str; - h ^= murmur_32_scramble(k); - h = (h << 13) | (h >> 19); - h = h * 5 + 0xe6546b64; + if (IS_ALIGNED(str, sizeof(uint32_t))) { + _LOOP(*(const uint32_t *)str); + } else { + _LOOP(UNALIGNED_GET((const uint32_t *)str)); } for (k = 0; n != 0; --n, ++str) { diff --git a/modules/lvgl/Kconfig b/modules/lvgl/Kconfig index 8084dd11a33..01e1ef004df 100644 --- a/modules/lvgl/Kconfig +++ b/modules/lvgl/Kconfig @@ -94,6 +94,10 @@ config LV_COLOR_16_SWAP bool "Swap the 2 bytes of RGB565 color." depends on LV_COLOR_DEPTH_16 +config LV_Z_COLOR_MONO_HW_INVERSION + bool "Hardware pixel inversion (disables software pixel inversion)." + depends on LV_COLOR_DEPTH_1 + config LV_Z_FLUSH_THREAD bool "Flush LVGL frames in a separate thread" help diff --git a/modules/lvgl/lvgl_display_mono.c b/modules/lvgl/lvgl_display_mono.c index 09b9bfd2337..069a0eea28b 100644 --- a/modules/lvgl/lvgl_display_mono.c +++ b/modules/lvgl/lvgl_display_mono.c @@ -38,17 +38,25 @@ static ALWAYS_INLINE void set_px_at_pos(uint8_t *dst_buf, uint32_t x, uint32_t y } } +#ifdef CONFIG_LV_Z_COLOR_MONO_HW_INVERSION + *buf |= BIT(bit); +#else if (caps->current_pixel_format == PIXEL_FORMAT_MONO10) { *buf |= BIT(bit); } else { *buf &= ~BIT(bit); } +#endif } static void lvgl_transform_buffer(uint8_t **px_map, uint32_t width, uint32_t height, const struct display_capabilities *caps) { +#ifdef CONFIG_LV_Z_COLOR_MONO_HW_INVERSION + uint8_t clear_color = 0x00; +#else uint8_t clear_color = caps->current_pixel_format == PIXEL_FORMAT_MONO10 ? 0x00 : 0xFF; +#endif memset(mono_conv_buf, clear_color, mono_conv_buf_size); diff --git a/subsys/debug/coredump/Kconfig b/subsys/debug/coredump/Kconfig index fdab0361820..1e763e522e1 100644 --- a/subsys/debug/coredump/Kconfig +++ b/subsys/debug/coredump/Kconfig @@ -144,4 +144,27 @@ module = DEBUG_COREDUMP module-str = coredump source "subsys/logging/Kconfig.template.log_config" +config DEBUG_COREDUMP_THREAD_STACK_TOP + bool "Dump top of stack only" + default y if DEBUG_COREDUMP_MEMORY_DUMP_MIN + depends on DEBUG_COREDUMP_MEMORY_DUMP_MIN || \ + DEBUG_COREDUMP_MEMORY_DUMP_THREADS + depends on ARCH_SUPPORTS_COREDUMP_STACK_PTR + help + This option enables dumping only the top portion of each thread's + stack, rather than the entire stack region. The top of the stack is + defined as the area from the stack pointer to the stack end, but the + size of this region can additionally be constrained using the + DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT option. + +config DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT + int "Stack top size limit" + default -1 + depends on DEBUG_COREDUMP_THREAD_STACK_TOP + help + See the description of the DEBUG_COREDUMP_THREAD_STACK_TOP option. + The value -1 indicates that there is no limit, meaning that the stack + is dumped till the end of its region. + + endif # DEBUG_COREDUMP diff --git a/subsys/debug/coredump/coredump_core.c b/subsys/debug/coredump/coredump_core.c index 12fa0fa8dfd..fc56e4cf3b6 100644 --- a/subsys/debug/coredump/coredump_core.c +++ b/subsys/debug/coredump/coredump_core.c @@ -41,6 +41,13 @@ static struct coredump_backend_api #define DT_DRV_COMPAT zephyr_coredump #endif +#if defined(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT) && \ + CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT > 0 +#define STACK_TOP_LIMIT ((size_t)CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT) +#else +#define STACK_TOP_LIMIT SIZE_MAX +#endif + #if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK) __weak void arch_coredump_priv_stack_dump(struct k_thread *thread) { @@ -70,10 +77,35 @@ static void dump_header(unsigned int reason) backend_api->buffer_output((uint8_t *)&hdr, sizeof(hdr)); } -#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \ +#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \ defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_THREADS) + +static inline void select_stack_region(const struct k_thread *thread, uintptr_t *start, + uintptr_t *end) +{ + uintptr_t sp; + + *start = thread->stack_info.start; + *end = thread->stack_info.start + thread->stack_info.size; + + if (!IS_ENABLED(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP)) { + return; + } + + sp = arch_coredump_stack_ptr_get(thread); + + if (IN_RANGE(sp, *start, *end)) { + /* Skip ahead to the stack pointer. */ + *start = sp; + } + + /* Make sure no more than STACK_TOP_LIMIT bytes of the stack are dumped. */ + *end = *start + MIN((size_t)(*end - *start), STACK_TOP_LIMIT); +} + static void dump_thread(struct k_thread *thread) { + uintptr_t start_addr; uintptr_t end_addr; /* @@ -86,13 +118,12 @@ static void dump_thread(struct k_thread *thread) return; } - end_addr = POINTER_TO_UINT(thread) + sizeof(*thread); - - coredump_memory_dump(POINTER_TO_UINT(thread), end_addr); - - end_addr = thread->stack_info.start + thread->stack_info.size; + start_addr = POINTER_TO_UINT(thread); + end_addr = start_addr + sizeof(*thread); + coredump_memory_dump(start_addr, end_addr); - coredump_memory_dump(thread->stack_info.start, end_addr); + select_stack_region(thread, &start_addr, &end_addr); + coredump_memory_dump(start_addr, end_addr); #if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK) if ((thread->base.user_options & K_USER) == K_USER) {