|  | 
|  | 1 | +# Zephyr Threading POC - Findings and Blockers | 
|  | 2 | + | 
|  | 3 | +## Summary | 
|  | 4 | + | 
|  | 5 | +Initial Proof of Concept attempt to integrate Zephyr kernel for threading in Unix port revealed significant integration challenges. While the concept is sound, the implementation complexity is higher than anticipated. | 
|  | 6 | + | 
|  | 7 | +## Work Completed | 
|  | 8 | + | 
|  | 9 | +### Infrastructure Created | 
|  | 10 | +1. ✅ `extmod/zephyr_kernel/` directory structure | 
|  | 11 | +2. ✅ `extmod/zephyr_kernel/zephyr_config.h` - Fixed CONFIG_ definitions (161 lines) | 
|  | 12 | +3. ✅ `extmod/zephyr_kernel/zephyr_kernel.h` - Integration API | 
|  | 13 | +4. ✅ `extmod/zephyr_kernel/kernel/mpthread_zephyr.c` - MicroPython threading API implementation (320 lines) | 
|  | 14 | +5. ✅ `ports/unix/zephyr_arch_unix.c` - Unix architecture layer (150 lines) | 
|  | 15 | +6. ✅ Modified `ports/unix/Makefile` - Added MICROPY_ZEPHYR_THREADING build option | 
|  | 16 | +7. ✅ Modified `ports/unix/mpthreadport.h` - Conditional compilation for Zephyr | 
|  | 17 | +8. ✅ Modified `ports/unix/main.c` - Handle different mp_thread_init signatures | 
|  | 18 | + | 
|  | 19 | +### Code Statistics | 
|  | 20 | +- Total new code: ~700 lines | 
|  | 21 | +- Modified existing code: ~50 lines | 
|  | 22 | +- Identified 18 Zephyr kernel files needed for minimal threading | 
|  | 23 | + | 
|  | 24 | +## Build Issues Encountered | 
|  | 25 | + | 
|  | 26 | +### Issue 1: Architecture Detection | 
|  | 27 | +**Problem**: Zephyr's `toolchain/gcc.h` didn't recognize x86_64 architecture. | 
|  | 28 | + | 
|  | 29 | +**Solution Attempted**: Added CONFIG_X86_64 and CONFIG_64BIT definitions to zephyr_config.h | 
|  | 30 | + | 
|  | 31 | +**Status**: ✅ Partially resolved (still some edge cases) | 
|  | 32 | + | 
|  | 33 | +### Issue 2: Missing Generated Headers | 
|  | 34 | +**Problem**: Zephyr build system generates several header files that don't exist in source: | 
|  | 35 | +- `zephyr/syscall_list.h` | 
|  | 36 | +- `zephyr/syscalls/time_units.h` | 
|  | 37 | +- `zephyr/syscalls/*.h` (various syscall headers) | 
|  | 38 | + | 
|  | 39 | +**Impact**: These are core to Zephyr's header structure. Stubbing them out causes cascading issues. | 
|  | 40 | + | 
|  | 41 | +**Root Cause**: Zephyr's header files are tightly coupled to the build system's code generation. | 
|  | 42 | + | 
|  | 43 | +**Status**: ⚠️ Partial workaround attempted, not fully resolved | 
|  | 44 | + | 
|  | 45 | +### Issue 3: Syscall System Integration | 
|  | 46 | +**Problem**: Zephyr uses a complex syscall system with: | 
|  | 47 | +- Macro-based syscall definitions | 
|  | 48 | +- Generated wrapper code | 
|  | 49 | +- Architecture-specific trampolines | 
|  | 50 | +- Userspace/kernel space separation | 
|  | 51 | + | 
|  | 52 | +**Attempted Solutions**: | 
|  | 53 | +1. Define `__syscall` as empty macro → Conflicts with Zephyr's definitions | 
|  | 54 | +2. Stub out syscall_list.h → Missing dependent generated files | 
|  | 55 | +3. Use `-D` to redefine includes → ISO C99 macro naming issues | 
|  | 56 | + | 
|  | 57 | +**Status**: ❌ Blocked - Syscall system deeply integrated into headers | 
|  | 58 | + | 
|  | 59 | +### Issue 4: Header Include Order Dependencies | 
|  | 60 | +**Problem**: Zephyr headers have complex include dependencies: | 
|  | 61 | +``` | 
|  | 62 | +kernel.h → kernel_includes.h → syscall.h → syscall_list.h (generated) | 
|  | 63 | +                             → toolchain.h → arch-specific headers | 
|  | 64 | +                             → sys/atomic.h → time_units.h → syscalls/time_units.h (generated) | 
|  | 65 | +``` | 
|  | 66 | + | 
|  | 67 | +**Impact**: Can't include `<zephyr/kernel.h>` without full build system | 
|  | 68 | + | 
|  | 69 | +**Status**: ❌ Fundamental architectural issue | 
|  | 70 | + | 
|  | 71 | +## Technical Analysis | 
|  | 72 | + | 
|  | 73 | +### Why Integration is Difficult | 
|  | 74 | + | 
|  | 75 | +1. **Generated Code Dependency** | 
|  | 76 | +   - Zephyr build generates ~20+ header files | 
|  | 77 | +   - These files contain syscall wrappers, device trees, Kconfig output | 
|  | 78 | +   - Not feasible to manually stub all of them | 
|  | 79 | + | 
|  | 80 | +2. **Tight Coupling to Build System** | 
|  | 81 | +   - CMake introspects source files to generate syscall lists | 
|  | 82 | +   - Kconfig generates configuration headers | 
|  | 83 | +   - Device tree compiler generates hardware definitions | 
|  | 84 | +   - Build system is not just configuration - it's code generation | 
|  | 85 | + | 
|  | 86 | +3. **Userspace/Kernel Separation** | 
|  | 87 | +   - Zephyr designed for userspace/kernel separation | 
|  | 88 | +   - Syscall mechanism is core architecture | 
|  | 89 | +   - Can't easily bypass for "kernel-only" use | 
|  | 90 | + | 
|  | 91 | +4. **Architecture-Specific Code** | 
|  | 92 | +   - Each arch has different header requirements | 
|  | 93 | +   - Context switching depends on arch-specific types | 
|  | 94 | +   - Atomic operations vary by architecture | 
|  | 95 | + | 
|  | 96 | +### What Would Be Needed for Success | 
|  | 97 | + | 
|  | 98 | +To make this work, would need: | 
|  | 99 | + | 
|  | 100 | +1. **Minimal Zephyr Build** | 
|  | 101 | +   - Run CMake to generate required headers | 
|  | 102 | +   - Extract only kernel .c files and generated headers | 
|  | 103 | +   - Package as pre-built component | 
|  | 104 | + | 
|  | 105 | +2. **Alternative: Header-Only Wrapper** | 
|  | 106 | +   - Don't use Zephyr headers at all | 
|  | 107 | +   - Manually reimplement minimal thread/mutex/sem types | 
|  | 108 | +   - Link against pre-compiled Zephyr kernel library | 
|  | 109 | + | 
|  | 110 | +3. **Alternative: Fork and Simplify** | 
|  | 111 | +   - Fork Zephyr kernel sources | 
|  | 112 | +   - Remove syscall system completely | 
|  | 113 | +   - Create standalone kernel library | 
|  | 114 | +   - High maintenance burden | 
|  | 115 | + | 
|  | 116 | +## Recommendations | 
|  | 117 | + | 
|  | 118 | +### Short Term: Alternative Approaches | 
|  | 119 | + | 
|  | 120 | +#### Option A: Pre-Generated Zephyr Build | 
|  | 121 | +1. Use Zephyr build system to compile kernel for each architecture | 
|  | 122 | +2. Package as static library + minimal headers | 
|  | 123 | +3. MicroPython ports link against pre-built library | 
|  | 124 | +4. **Pros**: Gets Zephyr functionality, avoids header issues | 
|  | 125 | +5. **Cons**: Adds binary dependency, complicates build | 
|  | 126 | + | 
|  | 127 | +#### Option B: Minimal Kernel Reimplementation | 
|  | 128 | +1. Study Zephyr's thread.c, sched.c, mutex.c implementations | 
|  | 129 | +2. Extract core algorithms | 
|  | 130 | +3. Reimplement in standalone files without Zephyr dependencies | 
|  | 131 | +4. **Pros**: Clean integration, no Zephyr coupling | 
|  | 132 | +5. **Cons**: Significant development effort, loses Zephyr updates | 
|  | 133 | + | 
|  | 134 | +#### Option C: Use Different RTOS | 
|  | 135 | +1. Consider lighter-weight RTOS (FreeRTOS, ThreadX, RT-Thread) | 
|  | 136 | +2. These have simpler header structures | 
|  | 137 | +3. **Pros**: Might integrate easier | 
|  | 138 | +4. **Cons**: Different feature set, less mature than Zephyr | 
|  | 139 | + | 
|  | 140 | +### Long Term: Unified Threading API | 
|  | 141 | + | 
|  | 142 | +Regardless of backend choice, create abstraction layer: | 
|  | 143 | + | 
|  | 144 | +```c | 
|  | 145 | +// extmod/mpthread_rtos.h - Unified RTOS threading API | 
|  | 146 | +typedef struct mp_rtos_thread mp_rtos_thread_t; | 
|  | 147 | +typedef struct mp_rtos_mutex mp_rtos_mutex_t; | 
|  | 148 | + | 
|  | 149 | +mp_rtos_thread_t* mp_rtos_thread_create(void *(*entry)(void*), void *arg); | 
|  | 150 | +void mp_rtos_mutex_init(mp_rtos_mutex_t *mutex); | 
|  | 151 | +// ... etc | 
|  | 152 | +``` | 
|  | 153 | +
 | 
|  | 154 | +Then implement for: | 
|  | 155 | +- Zephyr (if feasible) | 
|  | 156 | +- FreeRTOS | 
|  | 157 | +- ThreadX | 
|  | 158 | +- Pthreads (Unix/POSIX) | 
|  | 159 | +- Custom (STM32, RP2) | 
|  | 160 | +
 | 
|  | 161 | +## Lessons Learned | 
|  | 162 | +
 | 
|  | 163 | +1. **Header-Only Integration is Insufficient** | 
|  | 164 | +   - Modern RTOS frameworks rely on code generation | 
|  | 165 | +   - Can't just "include headers" without build system | 
|  | 166 | +
 | 
|  | 167 | +2. **Build System Complexity** | 
|  | 168 | +   - Zephyr's build system is integral, not optional | 
|  | 169 | +   - This was underestimated in initial research | 
|  | 170 | +
 | 
|  | 171 | +3. **Syscall System is Core** | 
|  | 172 | +   - Can't be easily disabled or stubbed | 
|  | 173 | +   - Permeates all Zephyr APIs | 
|  | 174 | +
 | 
|  | 175 | +4. **POC Validated Concerns** | 
|  | 176 | +   - Research document correctly identified this as high-risk | 
|  | 177 | +   - Build system integration was flagged as key challenge | 
|  | 178 | +   - Findings confirm need for different approach | 
|  | 179 | +
 | 
|  | 180 | +## Next Steps | 
|  | 181 | +
 | 
|  | 182 | +### Immediate Actions | 
|  | 183 | +
 | 
|  | 184 | +1. **Document Findings** ✅ (this document) | 
|  | 185 | +2. **Update Research Document** with lessons learned | 
|  | 186 | +3. **Propose Alternative Strategy** to user | 
|  | 187 | +
 | 
|  | 188 | +### Options for User | 
|  | 189 | +
 | 
|  | 190 | +**Option 1**: Accept limited scope | 
|  | 191 | +- Proceed with Unix POC using pthread-backed Zephyr API | 
|  | 192 | +- Don't use actual Zephyr kernel | 
|  | 193 | +- Just standardize API shape | 
|  | 194 | +- ~2 hours additional work | 
|  | 195 | +
 | 
|  | 196 | +**Option 2**: Use pre-built Zephyr libraries | 
|  | 197 | +- Set up proper Zephyr builds for each port | 
|  | 198 | +- Export as static libraries | 
|  | 199 | +- Higher complexity but gets real Zephyr | 
|  | 200 | +- ~1-2 days additional work | 
|  | 201 | +
 | 
|  | 202 | +**Option 3**: Pivot to different approach | 
|  | 203 | +- Abandon Zephyr integration | 
|  | 204 | +- Either keep port-specific threading OR | 
|  | 205 | +- Use simpler RTOS (FreeRTOS already used in ESP32) | 
|  | 206 | +- Design unified API over existing implementations | 
|  | 207 | +
 | 
|  | 208 | +**Option 4**: Minimal Zephyr fork | 
|  | 209 | +- Fork just kernel/ directory from Zephyr | 
|  | 210 | +- Strip out syscall dependencies | 
|  | 211 | +- Maintain as separate library | 
|  | 212 | +- ~2-3 days initial, ongoing maintenance | 
|  | 213 | +
 | 
|  | 214 | +## Conclusion | 
|  | 215 | +
 | 
|  | 216 | +The POC successfully demonstrated: | 
|  | 217 | +- ✅ API design is sound | 
|  | 218 | +- ✅ Integration points identified correctly | 
|  | 219 | +- ✅ Code structure is reasonable | 
|  | 220 | +- ⚠️ Build integration is more complex than anticipated | 
|  | 221 | +- ❌ Cannot use Zephyr headers without build system | 
|  | 222 | +
 | 
|  | 223 | +**Recommendation**: Either commit to full Zephyr build integration (Option 2) or pivot to alternative approach (Options 3 or 4). | 
|  | 224 | +
 | 
|  | 225 | +The "minimal extraction" approach (original plan) is not viable due to generated header dependencies. | 
0 commit comments