Skip to content

Conversation

@dmfaria
Copy link

@dmfaria dmfaria commented Jun 14, 2024

  1. Changed esp32c6 to 12 bits according to the specification (https://www.espressif.com/en/products/socs/esp32-c6)
  2. added CONFIG_IDF_TARGET_ESP32C6 to adc.c since this config was missiging

@andrewleech
Copy link
Owner

Thanks heaps for this, I hadn't found the time to look into the reported issues with the ADC so I really appreciate your work!

@andrewleech andrewleech merged commit 602a0f9 into andrewleech:esp32c6 Jun 20, 2024
@dmfaria dmfaria deleted the esp32c6-ADC-minorfix branch June 20, 2024 03:41
andrewleech pushed a commit that referenced this pull request Oct 27, 2025
Threads were hanging when executing Python functions due to two critical bugs
in the thread initialization path when MICROPY_ZEPHYR_THREADING is enabled:

Bug #1 - C Stack Initialization Corruption (runtime.h):
zephyr_entry() correctly sets C stack bounds using actual Zephyr thread
stack info, but mp_thread_init_state() was then overwriting those bounds
by calling mp_cstack_init_with_top(ts + 1, stack_size). The ts + 1 address
points to memory after a local variable, causing mp_cstack_check() to
calculate garbage values and potentially raise recursion depth errors.

Bug #2 - Thread State Pointer Corruption (modthread.c):
zephyr_entry() correctly sets TLS to heap-allocated self->thread_state,
but thread_entry() creates a local variable mp_state_thread_t ts and calls
mp_thread_init_state(&ts, ...) which overwrites the TLS pointer to point
to this local stack variable. When the stack frame changes, all
MP_STATE_THREAD() accesses point to invalid memory.

Root cause: For Zephyr threading there are two entry points:
1. zephyr_entry() - Zephyr thread entry that initializes MicroPython
2. thread_entry() - Generic MicroPython thread entry

The bugs occurred because thread_entry() was reinitializing everything
that zephyr_entry() had already correctly initialized, causing double
initialization and memory corruption.

Solution: Modified thread_entry() to skip thread state allocation,
C stack initialization, and mp_thread_start() call when Zephyr threading
is enabled, as these are already handled by zephyr_entry(). Thread_entry()
now only handles GIL, NLR, and function execution for Zephyr threading.

Changes:
- py/runtime.h: Skip mp_cstack_init_with_top() for Zephyr threading
- py/modthread.c: Skip thread state init and mp_thread_start() for Zephyr

Tested on STM32 NUCLEO_F429ZI (STM32F429ZITx).
Threads now successfully execute Python functions.

Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
andrewleech pushed a commit that referenced this pull request Nov 18, 2025
Test Results Summary:
- 24/34 tests passed (70.6%)
- 10/34 tests failed (29.4%)
- Firmware: v1.26.0-preview.323.g57456a5acc

Comparison to Baselines:
- Sprint 1 only (without two-phase): 6/33 passed (18.2%)
- Current (Sprint 1 + two-phase): 24/34 passed (70.6%)
- Improvement: +18 tests (+52.4 percentage points)

Sprint 1 Fixes Applied (commits 2032aa2, 724f018, 57456a5):
1. PRIMASK interrupt masking: arch_irq_lock() now masks ALL interrupts
2. Removed GC test instrumentation: Eliminated gc_recently_run causing MemoryErrors
3. PendSV delegation: Proper context switching via z_arm_pendsv

Two-Phase Initialization:
- Phase 1 (early): mp_thread_set_state() before gc_init() for MP_STATE_THREAD access
- Phase 2 (after GC): Allocate thread structures on GC heap with canary protection
- Required due to circular dependency: gc_init() needs thread state,
  mp_thread_init() needs GC heap

Tests Now Passing (vs Sprint 1 baseline):
- disable_irq, mutate_dict, mutate_instance, mutate_list, mutate_set
- stress_aes, thread_create_basic, thread_exc1, thread_exc2
- thread_exit1, thread_exit2, thread_gc1, thread_heap_lock
- thread_ident1, thread_lock1, thread_lock2, thread_lock5
- thread_shared1, thread_shared2, thread_sleep2, thread_stacksize1
- thread_start1, thread_start2, thread_stdin

Remaining Failures (10 tests):
- mutate_bytearray: Memory corruption during bytearray mutation
- stress_create, stress_heap, stress_recurse, stress_schedule:
  Resource exhaustion under heavy load
- thread_coop: Cooperative scheduling issues
- thread_lock3, thread_lock4: Advanced lock timeout/context manager scenarios
- thread_qstr1: QSTR allocation in threads
- thread_sleep1: Sleep precision/behavior

Known Issues from Code Review (ZEPHYR_THREADING_CODE_REVIEW.md):
1. Thread initialization race (Phase 2, Finding #1): Thread started with K_NO_WAIT
   before all fields initialized. If GC runs between k_thread_create() and field
   initialization, it scans garbage pointers.
   FIX: Initialize all fields before k_thread_create() or use K_FOREVER then
   k_thread_start().

2. Static name buffer race (Phase 2, Finding #2): Single static char name[16]
   shared across all threads causes corruption under concurrent creation.
   FIX: Allocate per-thread or embed in mp_thread_t structure.

3. Stack scanning fallback bug (Phase 2, Finding #3): On PSP corruption,
   falls back to scanning entire stack including garbage.
   FIX: Skip thread or halt, don't scan garbage.

Next Steps:
- Address thread initialization race (highest impact)
- Fix static name buffer race
- Investigate remaining 10 test failures
- Consider simplification to reduce maintenance burden (667 lines vs 308 in ports/zephyr)

Test Command:
  cd ~/micropython/tests && \
  env RESET='pyocd reset --probe 066CFF495177514867213407' \
  ./run-tests.py -t port:/dev/serial/by-id/usb-STMicroelectronics_STM32_STLink_066CFF495177514867213407-if02 \
  ~/micropython/tests/thread/*.py

Signed-off-by: Andrew Leech <andrew@alelec.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants