Getting Started With Apache MyNewt RTOS: Using SAMD21 and Nucleo L476RG Boards
— บทความภาษาไทย
Apache MyNewt RTOS: Using SAMD21 and Nucleo L476RG Boards
บทความนี้เป็นบันทึกช่วยจำ หลังจากได้ลองติดตั้งใช้งาน **Apache MyNewt สำหรับระบบปฏิบัติการ Windows 10 (64-bit) และได้นำมาลองใช้กับบอร์ดไมโครคอนโทรลเลอร์ ATSAMD21 (Arduino Zero Compatible) และ Nucleo L476RG **ตามลำดับ
Apache MyNewt มีการเปิดตัวครั้งแรกในค.ศ. 2016 ปัจจุบันอยู่ภายใต้การดูแลโดยบริษัท Runtime Inc. เป็นระบบปฏิบัติการเวลาจริง หรือ “เรียลไทม์โอเอส” (RTOS) แบบ Open Source (Apache License 2.0) เหมาะสำหรับนำมาใช้กับไมโครคอนโทรลเลอร์ 32 บิต สำหรับงานด้าน IoT (Internet of Things) มีตัวเคอร์เนล (Kernel) ที่ทำงานแบบ Priority-based Pre-emptive Scheduling
Apache MyNewt สามารถนำมาใช้ได้กับไมโครคอนโทรลเลอร์ 32 บิต ได้หลายตระกูลและบริษัทผู้ผลิต เช่น
- **STMicroelectronics (STM32F0/F1/F3/F7/L0/L1/L4)**
- **Nordic (nRF51/nRF52)**
- **NXP (MK64F)**
- **Microchip (PIC32MX/MZ)**
- **SiFive (HiFive1)**
- Atmel/Microchip (ATSAMD21G18)
ฟีเจอร์หลักของ Apache MyNewt OS
- Multi-threading รองรับการเขียนโปรแกรมแบบมัลติทาสกิ้ง (อาจใช้คำว่า Task และ Thread แทนกันได้)
- Priority-based Preemptive Scheduling รองรับการจัดตารางการทำงานของทาส์กตามลำดับความสำคัญ (Priority) ตั้งแต่ 0 (สูงสุด) ถึง 255 (ต่ำสุด)และอนุญาตให้ทาส์กที่มีความสำคัญสูงกว่าแทรกการทำงานของทาสก์ที่มีความสำคัญต่ำกว่าได้
- Tickless Scheduling รองรับการจัดตารางการทำงานของทาส์กแบบไม่ใช้ OS Ticks และเหมาะสำหรับระบบที่ต้องการประหยัดหรือใช้พลังงานต่ำ (ให้ซีพียูเข้าสู่ Sleep Mode ถ้าไม่มีทาสก์ใดทำงาน)
- System Time Management มีคำสั่งของ API สำหรับการจัดการเกี่ยวกับเวลาของระบบ
- Inter-Task Synchronization & Communications มีคำสั่งของ API ที่ใช้สำหรับการประสานการทำงานและสื่อสารกันระหว่างทาส์กได้ เช่น Semaphores, Mutexes
- Event-Driven Model จัดการเหตุการณ์ของระบบโดยใช้ Event Queues
- Memory Management (Dynamic Allocation) มีคำสั่งของ API สำหรับจัดการหน่วยความจำ เช่น การจองและคืนหน่วยความจำสำหรับ Heap Memory และ Memory Pool เป็นต้น
- Software Timers (Callouts) สามารถใช้เป็นตัวจับเวลาได้และสร้างเหตุการณ์เมื่อระยะเวลาผ่านไปตามที่ต้องการ
- Software Watchdog Timer คอยตรวจสอบการทำงานของระบบตามช่วงเวลา
นอกจาก Real-Time Kernel แล้ว ยังมี API สำหรับฟังก์ชันการทำงาน เช่น
- HAL (Hardware Abstraction Layer) for Device Drivers / MCU-Specific BSP (Board Support Packages) สำหรับการใช้งานเช่น GPIO, PWM, UART, SPI, I2C, ADC, DAC เป็นต้น
- Newtron Flash File System (“nffs”) เป็นระบบไฟล์สำหรับหน่วยความจำแบบ Flash เช่น การสร้างไฟล์ การเปิดไฟล์เพื่อเขียนอ่านข้อมูล เป็นต้น
- Secure boot loader (“MCUboot”) จะทำงานเมื่อมีการรีเซตหรือเปิดระบบทำงาน และสามารถตรวจสอบความถูกต้องของไฟล์ Application Image (.img) โดยใช้ SHA-256 (Secure Hash) ได้ หรือใช้วิธีการอื่นสำหรับ Digital Signature Verification
- Console, Statistics and Logs สำหรับการเข้าถึงระบบผ่าน Serial Console การเก็บสถิติการทำงานของทาส์กต่าง ๆ และบันทึกเหตุการณ์ของระบบ เป็นต้น
- NimBLE เป็นไลบรารีสำหรับ Bluetooth Stack รองรับการใช้งาน Bluetooth Low Energy (BLE) และ BLE Mesh
- Network Stacks: TCP/IP, UDP, CoAP, Wi-Fi, LoRaWAN, 6LowPAN, Thread

Apache MyNewt Logo
ขั้นตอนการดำเนินการ
- ดาวน์โหลดและติดตั้ง GNU ARM Embedded Toolchain (ุถ้ายังไม่เคยได้ติดตั้งใช้งาน) [**Download Site**]
- ดาวน์โหลดและติดตั้ง OpenOCD for Windows (ถ้ายังไม่เคยได้ติดตั้งใช้งาน) [**Download Site**]
- ตาวน์โหลดและติดตั้ง MSYS2-MINGW64 สำหรับระบบปฏิบัติการ Windows 10 (ถ้ายังไม่เคยติดตั้งใช้งาน) [**Download Site**]
- เรียกใช้งาน MSYS2-MINGW64 Terminal
- ดาวน์โหลดและติดตั้ง Newt Tools for Windows (ได้เลือกใช้เวอร์ชัน 1.7.0) สำหรับ Apache MyNewt
- สร้างโปรเจกต์ใหม่ และอัปเดต Repositories ที่จำเป็นต้องใช้ โดยจะนำมาใช้สำหรับบอร์ด **RobotDyn SAMD21 M0-Mini (Arduino Zero Compatible**)
- ทดลองขั้นตอนเหมือนเดิม แต่เลือกใช้บอร์ด Nucleo L476RG
ศึกษาเพิ่มเติม: บนเว็บไซต์ของ Apache MyNewt มีเขียนอธิบายขั้นตอนการติดตั้ง **ARM Cross Toolchain และ [OpenOCD](https://mynewt.apache.org/latest/get_started/native_install/cross_tools.html#installing-the-debuggers) **ไว้ให้ศึกษาด้วย
ข้อสังเกต: โปรแกรม Newt Tool ของ Apache MyNewt นั้นมีให้เลือกใช้สำหรับระบบปฏิบัติการ Windows, Ubuntu และ Mac OS X
การดาวน์โหลดและติดตั้ง Newt Tool
Newt เป็นโปรแกรมที่ใช้ภาษา Go ในการเขียนโค้ด จัดอยู่ในประเภท CLI (Command Line Interface) และใช้สำหรับการสร้างโปรเจกต์และขั้นตอนต่าง ๆ ที่เกี่ยวข้องสำหรับ Apache MyNewt เวอร์ชันล่าสุดที่ได้นำมาใช้คือ v1.7.0
เมื่อเปิด Terminal ของ MSYS2-MINGW64 แล้ว ให้ทำคำสั่งต่อไปนี้ เพื่อดาวน์โหลด .tgz จากนั้นแตกไฟล์ แล้วติดตั้งไปยังไดเรกทอรี /usr/bin
$ wget https://downloads.apache.org/mynewt/apache-mynewt-1.7.0/apache-mynewt-newt-bin-windows-1.7.0.tgz
$ tar -xzf apache-mynewt-newt-bin-windows-1.7.0.tgz
$ cp apache-mynewt-newt-bin-windows-1.7.0/newt.exe /usr/bin/
ถ้าไม่มีคำสั่ง เช่น tar หรือ wget ก็สามารถติดตั้งเพิ่มได้ เหมือนกรณีของ Ubuntu แต่ใช้คำสั่ง pacman ตามตัวอย่างดังนี้
pacman -S --needed tar wget
จากนั้นให้ลองเรียกใช้คำสั่ง newt ดังนี้
$ newt version
ตัวอย่างเอาต์พุตที่ได้
Apache Newt
Version: 1.7.0
Git Hash: 80bcba7
Build Date: 2019-07-17_13:51
อีกโปรแกรมหนึ่งที่แนะนำให้ติดตั้งคือ Newt Manager (newtmgr) โดยทำคำสั่งดังนี้
$ wget https://downloads.apache.org/mynewt/apache-mynewt-1.7.0/apache-mynewt-newtmgr-bin-windows-1.7.0.tgz
$ tar xvzf apache-mynewt-newtmgr-bin-windows-1.7.0.tgz -C
$ cp apache-mynewt-newtmgr-bin-windows-1.7.0/newtmgr.exe /usr/bin/
ถัดไปให้ลองทำคำสั่งเพื่อตรวจสอบดูว่า เราได้สามารถใช้คำสั่ง arm-none-eabi-gcc และ openocd ได้หรือไม่
$ arm-none-eabi-gcc --version | head -1
$ openocd --version | head -1
ตัวอย่างเอาต์พุตที่ได้สำหรับคำสั่งแรก
arm-none-eabi-gcc.exe (GNU Tools for Arm Embedded Processors 8-2018-q4-major) 8.2.1 20181213 (release) [gcc-8-branch revision 267074]
และคำสั่งที่สอง ตามลำดับ
Open On-Chip Debugger 0.10.0+dev-01040-ge7e681ac (2020-03-04-16:05)
การสร้างโปรเจกต์ใหม่ LED Blink
ถัดไปเป็นขั้นตอนสร้างโปรเจกต์ใหม่ โดยทำคำสั่งต่อไปนี้ และเมื่อทำแล้ว จะได้ไดเรกทอรีใหม่ตามชื่อโปรเจกต์ ในตัวอย่างนี้เราใช้ชื่อว่า mynewt_demo
$ newt new mynewt_demo
$ cd mynewt_demo
ภายในไดเรกทอรีของโปรเจกต์ใหม่นี้ เมื่อเริ่มต้น มีโครงสร้างของไฟล์ดังนี้
mynewt_demo/
├── apps
│ └── blinky
│ ├── pkg.yml
│ └── src
│ └── main.c
├── LICENSE
├── NOTICE
├── project.yml
├── README.md
└── targets
├── my_blinky_sim
│ ├── pkg.yml
│ └── target.yml
└── unittest
├── pkg.yml
└── target.yml
ข้อสังเกต: ภายใต้ไดเรกทอรี
targets/เราสามารถลบทิ้งได้ เพราะเราจะไม่ได้นำมาใช้
ภายในไดเรกทอรีใหม่นี้ มีไฟล์ project.yml ซึ่งมีไว้สำหรับการตั้งค่าต่าง ๆ ให้แก่โปรเจกต์ ถัดไปให้แก้ไขไฟล์ดังกล่าว ตามตัวอย่างต่อไปนี้
project.name: "mynewt_demo"
project.repositories:
- apache-mynewt-core
- mynewt_arduino_zero
repository.apache-mynewt-core:
type: github
vers: 0-dev
user: apache
repo: mynewt-core
repository.mynewt_arduino_zero:
type: github
vers: 0-dev
user: runtimeco
repo: mynewt_arduino_zero
จากนั้นจะต้องทำคำสั่งต่อไปนี้ เพื่อติดตั้งและอัปเกรด Repositories (ดึงมาจาก Github) ที่จำเป็นต้องใช้
$ newt upgrade -v -f
ในตัวอย่าง มีการระบุไว้ 2 รายการ ดังนี้
apache-mynewt-coreเป็น Core ของ Apache MyNewtmynewt_arduino_zeroมี BSP (Board Support Package) และ HAL (Hardware Abstraction Layer) Implementation สำหรับบอร์ดไมโครคอนโทรลเลอร์ SAMD21G18 (Arduino Zero Compatible)
หลังจากทำคำสั่งแล้ว โครงสร้างไฟล์ของโปรเจกต์ จะเป็นดังนี้
.
├── apps
│ └── blinky
├── bin
│ └── targets
├── LICENSE
├── NOTICE
├── project.yml
├── README.md
├── repos
│ ├── apache-mynewt-core
│ ├── apache-mynewt-mcumgr
│ ├── apache-mynewt-nimble
│ ├── mcuboot
│ └── mynewt_arduino_zero
└── targets
การสร้าง Target สำหรับ Bootloader และ Application
การเขียนโค้ดโดยใช้ Apache MyNewt แล้วทำขั้นตอน Build เพื่อให้ได้ไฟล์สำหรับนำไปใช้กับบอร์ดไมโครคอนโทรลเลอร์เป้าหมาย แบ่งได้เป็น 2 ส่วนคือ ส่วนที่เป็น Apache MyNewt Bootloader และส่วนที่เป็น Application และทั้งสองส่วน (เรียกว่า Target) มีขั้นตอนดำเนินการแยกกัน โดยให้ทำส่วนที่เป็น Bootloader ก่อน
- ลำดับการคำสั่งเพื่อสร้าง Target สำหรับ Bootloader
# Create a new target 'samd21_boot'
$ newt target create samd21_boot
$ newt target set samd21_boot app=@mcuboot/boot/mynewt
$ newt target set samd21_boot \
bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero
$ newt target set samd21_boot build_profile=optimized
$ newt target set samd21_boot syscfg=BSP_ARDUINO_ZERO=1
# Build the Bootloader
$ newt build samd21_boot
ปัญหาที่พบ: เมื่อทำขั้นตอน Build Target สำหรับ Arduino Zero ด้วยคำสั่งตามที่ระบุไว้ จะเกิด Errors ในขั้นตอนการคอมไพล์โค้ด เนื่องจากไม่ได้มีการประกาศและสร้างฟังก์ชันชื่อ
hal_debug_break()ในไฟล์[hal_debug.h](https://github.com/apache/mynewt-core/blob/master/hw/hal/include/hal/hal_debug.h) วิธีแก้ไขคือ ให้เพิ่มโค้ดบรรทัดต่อไปนี้ ในไฟล์mynewt_arduino_zero/hw/mcu/atmel/samd21xx/include/mcu/cortex_m0.h
static inline void hal_debug_break(void) { __BKPT(1); }
เมื่อแก้ไขแล้วทำคำสั่งเพื่อ Build ไฟล์สำหรับ Bootloader แล้ว เป็นไฟล์ .bin ตามนี้
bin/targets/samd21_boot/app/boot/mynewt/mynewt.elf.bin
ถัดไปจะเป็นการเขียนไฟล์ Bootloader ไปยังบอร์ด ATSAMD21 (เลือกใช้บอร์ด RobotDyn SAMD21 M0-Mini) โดยเลือกใช้อุปกรณ์ J-Link Debug Probe (ใช้ร่วมกับ WinUSB Driver) ที่เชื่อมต่อกับบอร์ดเป้าหมายด้วยวิธี SWD (Serial Wire Debug) และจะต้องใช้คำสั่ง openocd สำหรับขั้นตอนนี้
แต่ก่อนจะทำคำสั่งต่อไป ให้แก้ไขไฟล์ต่อไปนี้
repos/mynewt_arduino_zero/hw/bsp/arduino_zero/arduino_zero.cfg
เพื่อเปลี่ยนการตั้งค่าสำหรับ OpenOCD โดยเปลี่ยนจาก CMSIS-SWD (บอร์ด Arduino Zero ใช้กับ Atmel EDBG แบบ CMSIS-DAP SWD) เป็นการใช้งานอุปกรณ์ J-Link SWD แทนการใช้ Atmel EDBG
# use J-Link debug probe and SWD interface
interface jlink
transport select swd
# chip name
set CHIPNAME at91samd21g18
set CPUTAPID 0x0bc11477
set ENDIAN little
set _TARGETNAME $CHIPNAME.cpu
source [find target/at91samdXX.cfg]
$_TARGETNAME configure -event gdb-detach {if {[at91samd21g18.cpu curstate] eq "halted"} resume;shutdown}
จากนั้นจึงทำคำสั่งเพื่อเขียนไฟล์ Bootloader ไปยังชิปเป้าหมาย (ทำเพียงครั้งเดียว)
$ newt load samd21_boot
2. ลำดับการทำคำสั่งเพื่อสร้าง Target สำหรับ Application (Blinky)
เราจะแก้ไขไฟล์ main.c ในไดเรกทอรี apps/blinky ดังนี้
#define LED_PIN (17) // Arduino Pin = D13
#include <sysinit/sysinit.h>
#include <os/os.h>
#include <bsp/bsp.h>
#include <hal/hal_gpio.h>
int main(int argc, char **argv) {
sysinit(); // system initialization
hal_gpio_init_out( LED_PIN, 0 ); // LED low
while (1) {
hal_gpio_toggle( LED_PIN ); // toggle the LED
os_time_delay( OS_TICKS_PER_SEC/2 ); // 0.5 sec
}
return 0;
}
จากนั้นจึงทำขั้นตอนเพื่อสร้าง Target สำหรับ apps/blinky ตามลำดับดังนี้
$ newt target create 'samd21_blinky'
$ newt target set samd21_blinky app=apps/blinky
$ newt target set samd21_blinky \
bsp=@mynewt_arduino_zero/hw/bsp/arduino_zero
$ newt target set samd21_blinky build_profile=optimized
$ newt target set samd21_blinky syscfg=BSP_ARDUINO_ZERO=1
# Build the Application Blinkly
$ newt build samd21_blinky
เมื่อทำคำสั่งแล้ว โครงสร้างของไฟล์ในไดเรกทอรีสำหรับโปรเจกต์ เป็นดังนี้
.
├── apps
│ └── blinky
├── bin
│ └── targets
├── LICENSE
├── NOTICE
├── project.yml
├── README.md
├── repos
│ ├── apache-mynewt-core
│ ├── apache-mynewt-mcumgr
│ ├── apache-mynewt-nimble
│ ├── mcuboot
│ └── mynewt_arduino_zero
└── targets
├── samd21_blinky
└── samd21_boot
จากนั้นให้ทำคำสั่งเพื่อสร้างไฟล์ image (.img) และจะต้องระบุเวอร์ชันด้วย เช่น 1.0.0
# create the image for the target and specified version
$ newt create-image samd21_blinky 1.0.0
ซึ่งจะได้ไฟล์ .img ดังนี้
bin/targets/samd21_blinky/app/apps/blinky/blinky.img
และสุดท้ายจึงทำคำสั่งเพื่ออัปโหลดไฟล์ image ไปยังบอร์ดเป้าหมาย
# upload the application image to the target device
$ newt load samd21_blinky
ถ้าจะทำคำสั่งหลายคำสั่งต่อกัน ก็สามารถเขียนได้ดังนี้
$ MY_APP=samd21_blinky; \
newt build $MY_APP && \
newt create-image $MY_APP 1.0.0 && \
newt load $MY_APP
แก้ไขโค้ด main.c เช่น เพื่อลองใช้คำสั่ง printf() เป็นต้น เพื่อส่งข้อความไปยังคอมพิวเตอร์ปผ่านทาง USART (SERCOM2 ของ ATSAMD21) ใช้ค่า Baudrate 115200 และจะต้องมีอุปกรณ์ USB-to-Serial (3.3V logic level) นำมาต่อกับบอร์ดที่ขา {TX, RX, GND} ของบอร์ด RobotDyn M0- Mini
แก้ไขโค้ดในไฟล์ apps/blinky/src/main.c ตามตัวอย่าง
#define LED_PIN (27) // use onboard LED
#include <stdio.h>
#include <string.h>
#include <sysinit/sysinit.h>
#include <console/console.h>
#include <os/os.h>
#include <bsp/bsp.h>
#include <hal/hal_gpio.h>
int main(int argc, char **argv) {
uint32_t cnt = 0;
sysinit(); // system initialization
hal_gpio_init_out( LED_PIN, 0 ); // LED low
console_printf( "Apache MyNewt on SAMD21...!!!\n" );
while (1) {
printf( "count: %lu\r\n", cnt++ );
hal_gpio_toggle( LED_PIN ); // toggle the LED
os_time_delay( OS_TICKS_PER_SEC/10 ); // 0.1 sec
}
return 0;
}
แก้ไขไฟล์ apps/blinky/pkg.yml
pkg.name: apps/blinky
pkg.type: app
pkg.description: Basic example application which blinks an LED.
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
pkg.deps:
- "@apache-mynewt-core/kernel/os"
- "@apache-mynewt-core/hw/hal"
- "@apache-mynewt-core/sys/console/full"
- "@apache-mynewt-core/sys/log/full"
ลองใช้ Apache MyNewt กับบอร์ด Nucleo L476RG
ถัดไปลองมาเขียนโปรแกรมโดยใช้ Apache MyNewt เพื่อนำไปทดสอบกับบอร์ด Nucleo L476RG ซึ่งมีวงจรที่ทำหน้าที่เป็น ST-Link V2 Programmer / Debugger มาให้แล้ว และไม่ได้ใช้ J-Link Debug Probe
- สร้าง Target สำหรับ Bootloader
$ newt target create nucleo_l476rg_boot
$ newt target set nucleo_l476rg_boot app=@mcuboot/boot/mynewt
$ newt target set nucleo_l476rg_boot \
bsp=@apache-mynewt-core/hw/bsp/nucleo-l476rg
$ newt target set nucleo_l476rg_boot build_profile=optimized
$ newt build nucleo_l476rg_boot
$ newt load nucleo_l476rg_boot
การอัปโหลดไฟล์ไปยังบอร์ด Nucleo ของ STMicroelectronics จะทำโดยใช้ไฟล์
repos/apache-mynewt-core/hw/scripts/stlink.sh
ซึ่งจะต้องมีการเรียกใช้คำสั่งชื่อ [st-flash](https://github.com/texane/stlink) (ใช้เวอร์ชัน 1.6.0 สำหรับ Windows) ดังนั้นจะต้องติดตั้งโปรแกรมนี้ ให้สามารถเรียกใช้ได้ก่อนทำขั้นตอนถัดไป
- สร้าง Target สำหรับ Application (Blinky)
เราสามารถใช้ไฟล์ตัวอย่าง apps/blinky/src/main.c แต่จะต้องกำหนดขา GPIO สำหรับ Onboard LED ให้ถูกต้อง เช่น ใช้ชื่อสัญลักษณ์ ARDUINO_PIN_D13 ก็สามารถดูรายละเอียดได้จากไฟล์ [bsp.h](https://github.com/apache/mynewt-core/blob/master/hw/bsp/nucleo-l476rg/include/bsp/bsp.h) สำหรับบอร์ดดังกล่าว
$ newt target create nucleo_l476rg_blinky
$ newt target set nucleo_l476rg_blinky app=apps/blinky
$ newt target set nucleo_l476rg_blinky \
bsp=@apache-mynewt-core/hw/bsp/nucleo-l476rg
$ newt target set nucleo_l476rg_blinky build_profile=optimized
สร้างไฟล์ Image แล้วอัปโหลดไปยังบอร์ด Nucleo L476RG
$ MY_APP=nucleo_l476rg_blinky; \
newt build $MY_APP && \
newt create-image $MY_APP 1.0.0 && \
newt load $MY_APP
ลองเขียนโดยใช้ Microsoft VSCode
เราสามารถใช้ IDE อย่างเช่น VSCode ที่ได้มีการติดตั้ง Extension “cpptools” แล้วนำมาใช้กับ Source Code Project ของ Apache MyNewt ตามรูปตัวอย่างนี้

การใช้ VSCode สำหรับการเขียนโปรแกรม

การเรียกใช้ Tasks: Run Task (Custom)

ตัวอย่างการทำคำสั่ง Newt สำหรับขั้นตอน Build Application
โดยสรุป: เราสามารถใช้งาน Apache MyNewt ร่วมกับบอร์ดไมโครคอนโทรลเลอร์ที่ใช้บอร์ด ATSAMD21 (Arduino Zero Compatible) และบอร์ด Nucleo L476RG ได้ และได้ติดตั้งโปรแกรมต่าง ๆ เพื่อใช้งานสำหรับระบบปฏิบัติการ Windows 10
ตัวอย่างที่ได้ลองไปนั้น ยังเป็นแค่ LED Blink ง่าย ๆ แต่เมื่อเรามีเครื่องมือพร้อมแล้ว เราก็สามารถเรียนรู้การทำงานของ Apache MyNewt เป็นลำดับต่อไปได้ เช่น การสร้างทาส์ก การเขียนโค้ดแบบมัลติทาสกิ้ง การประสานการทำงานและการสื่อสารระหว่างทาสก์ เป็นต้น
메타데이터
- post_id
- 2666bdda5088
- slug
- using-apache-mynewt-rtos-arduino-zero-compatible-board-and-nucleo-l476rg-board-2666bdda5088
- url
- https://medium.com/@rawats/using-apache-mynewt-rtos-arduino-zero-compatible-board-and-nucleo-l476rg-board-2666bdda5088
- canonical_url
- https://medium.com/@rawats/using-apache-mynewt-rtos-arduino-zero-compatible-board-and-nucleo-l476rg-board-2666bdda5088
- author_url
- https://medium.com/@rawats
- status
- ok
- fetched_at
- 2026-07-16 00:29:35