Browse Source

new: シングルコア設定を追加

Satoshi Yoneda 4 tuần trước cách đây
mục cha
commit
0360280dec

+ 40 - 1
README.md

@@ -163,6 +163,26 @@ target_link_libraries(your_project_name
 )
 ```
 
+### ビルドオプション(シングルコア構成の選択)
+
+tinykernel はデフォルトで RP2350 のデュアルコア SMP(対称型マルチプロセッシング)構成で動作します。
+もし Core 1 を独自の極めてビジーな処理(ベアメタル制御、専用の超高速ループなど)に専有し、tinykernel を Core 0 のみで動かしたい場合は、`TK_ENABLE_SMP` オプションを `OFF` に設定できます。
+
+- **CMake オプション設定**:
+  ```cmake
+  # add_subdirectory(tinykernel) の前に設定する場合
+  set(TK_ENABLE_SMP OFF CACHE BOOL "Enable SMP dual-core support" FORCE)
+  add_subdirectory(tinykernel)
+  ```
+  またはコマンドラインから設定:
+  ```bash
+  cmake -B build -DTK_ENABLE_SMP=OFF
+  ```
+
+- **シングルコア構成時の動作**:
+  - `multicore_launch_core1()` が実行されず、Core 1 は tinykernel から完全に解放されます(ユーザーコードから自由に `multicore_launch_core1(...)` などを利用可能)。
+  - Core 1 用アイドルタスクが生成されないため、利用可能なユーザータスク数が 30 個から 31 個に拡張されます。
+
 ---
 
 ## English Description
@@ -307,7 +327,7 @@ When performing peripheral transactions (such as I2C or SPI) where you want to p
 
 To integrate `tinykernel` into your Pico project, simply add the directory to your `CMakeLists.txt` and link it:
 
-```cpp
+```cmake
 add_subdirectory(tinykernel)
 
 target_link_libraries(your_project_name
@@ -315,3 +335,22 @@ target_link_libraries(your_project_name
     tinykernel_lib
 )
 ```
+
+### Build Option (Single Core Configuration)
+
+By default, `tinykernel` runs in SMP dual-core mode on RP2350.
+If you want to dedicate Core 1 to bare-metal polling / high-frequency routines and restrict `tinykernel` to Core 0 only, disable `TK_ENABLE_SMP`:
+
+```cmake
+# When embedding via add_subdirectory
+set(TK_ENABLE_SMP OFF CACHE BOOL "Enable SMP dual-core support" FORCE)
+add_subdirectory(tinykernel)
+```
+or via CLI:
+```bash
+cmake -B build -DTK_ENABLE_SMP=OFF
+```
+
+When SMP is disabled:
+- `multicore_launch_core1()` is not called; Core 1 is untouched and free for custom user control.
+- Max user tasks increase from 30 to 31 (since the Core 1 idle task is omitted).

+ 9 - 1
tinykernel/CMakeLists.txt

@@ -1,12 +1,13 @@
 # tinykernel: minimal preemptive task scheduler library (RP2350 / Pico 2)
 
+option(TK_ENABLE_SMP "Enable dual-core SMP support in tinykernel" ON)
+
 add_library(tinykernel_lib STATIC
     src/scheduler.cpp
     src/port/m33/port_m33.c
     src/port/m33/context.S
 )
 
-
 target_include_directories(tinykernel_lib PUBLIC
     ${CMAKE_CURRENT_LIST_DIR}/include
 )
@@ -17,3 +18,10 @@ target_link_libraries(tinykernel_lib PUBLIC
     hardware_sync
 )
 
+if(NOT TK_ENABLE_SMP)
+    target_compile_definitions(tinykernel_lib PUBLIC TK_ENABLE_SMP=0)
+    message(STATUS "tinykernel: SMP disabled (single-core mode on Core 0)")
+else()
+    target_compile_definitions(tinykernel_lib PUBLIC TK_ENABLE_SMP=1)
+    message(STATUS "tinykernel: SMP enabled (dual-core mode)")
+endif()

+ 10 - 1
tinykernel/include/tinykernel/kernel.hpp

@@ -16,7 +16,16 @@
 #define TK_TIME_SLICE_MS 10u
 #endif
 
-/** 最大タスク数 (スロット0はCore0アイドル、スロット1はCore1アイドル専用) */
+/** 使用するコア数 (1 または 2)。デフォルトは 2 (SMP) */
+#ifndef TK_NUM_CORES
+#if defined(TK_ENABLE_SMP) && !TK_ENABLE_SMP
+#define TK_NUM_CORES 1u
+#else
+#define TK_NUM_CORES 2u
+#endif
+#endif
+
+/** 最大タスク数 (スロット0はCore0アイドル、SMP時はスロット1がCore1アイドル専用) */
 #ifndef TK_MAX_TASKS
 #define TK_MAX_TASKS 32u
 #endif

+ 9 - 5
tinykernel/src/scheduler.cpp

@@ -15,8 +15,6 @@ static_assert(sizeof(FpuCtx) == 128, "FPU context layout must match context.S");
 
 namespace {
 
-constexpr uint32_t TK_NUM_CORES = 2;
-
 enum class State : uint8_t { Free = 0, Ready, Running, Sleeping, Blocked, Terminated };
 
 struct TaskSlot {
@@ -34,11 +32,15 @@ struct TaskSlot {
 
 static_assert(TK_MAX_TASKS <= 255, "slot index must fit in a byte");
 
-alignas(16) static TaskSlot g_slots[TK_MAX_TASKS];  // slot 0 = idle0, slot 1 = idle1
+alignas(16) static TaskSlot g_slots[TK_MAX_TASKS];  // slot 0 = idle0, slot 1 = idle1 (if SMP)
 alignas(8) static char g_stacks[TK_MAX_TASKS][TK_DEFAULT_STACK_SIZE];
 
+#if TK_NUM_CORES > 1
 static uint8_t g_cur[TK_NUM_CORES] = {0, 1};
-static volatile uint32_t g_preempt_disabled[TK_NUM_CORES] = {0, 0};
+#else
+static uint8_t g_cur[TK_NUM_CORES] = {0};
+#endif
+static volatile uint32_t g_preempt_disabled[TK_NUM_CORES] = {0};
 static int64_t g_tick = 0;
 static bool g_started = false;
 static uint8_t g_rr_last[16] = {0};
@@ -110,7 +112,7 @@ static uint32_t select_next(uint32_t core) {
 
 // Referenced (unmangled) from context.S: scratch area per-core for FPU state transfer.
 extern "C" {
-    alignas(8) FpuCtx tk_fpu_scratch[TK_NUM_CORES] = {};
+    alignas(8) FpuCtx tk_fpu_scratch[2] = {};
 }
 
 // SysTick interrupt handler: advances ticks on Core 0, wakes sleeping tasks, and checks time slices.
@@ -258,6 +260,7 @@ void tk::start() {
     idle0.is_idle = true;
     idle0.state = State::Ready;
 
+#if TK_NUM_CORES > 1
     // Core 1 Idle Task
     TaskSlot& idle1 = g_slots[1];
     idle1.fn = idle_fn;
@@ -268,6 +271,7 @@ void tk::start() {
 
     // Launch Core 1
     multicore_launch_core1(core1_entry);
+#endif
 
     // Launch Core 0
     core_start_routine(0);