Apache MyNewt RTOS: Using SAMD21 and Nucleo L476RG Boards

<rawat.s>
7 min readMar 6, 2020

--

‍‍‍‍‍‍ ‍‍ ‍‍‍‍‍‍ ‍‍‍‍‍‍ ‍‍

บทความนี้เป็นบันทึกช่วยจำ หลังจากได้ลองติดตั้งใช้งาน 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 บิต ได้หลายตระกูลและบริษัทผู้ผลิต เช่น

ฟีเจอร์หลักของ 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 ไว้ให้ศึกษาด้วย

ข้อสังเกต: โปรแกรม 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 MyNewt
  • mynewt_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 ก่อน

  1. ลำดับการคำสั่งเพื่อสร้าง 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 วิธีแก้ไขคือ ให้เพิ่มโค้ดบรรทัดต่อไปนี้ ในไฟล์ 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

  1. สร้าง 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 (ใช้เวอร์ชัน 1.6.0 สำหรับ Windows) ดังนั้นจะต้องติดตั้งโปรแกรมนี้ ให้สามารถเรียกใช้ได้ก่อนทำขั้นตอนถัดไป

2. สร้าง Target สำหรับ Application (Blinky)

เราสามารถใช้ไฟล์ตัวอย่าง apps/blinky/src/main.c แต่จะต้องกำหนดขา GPIO สำหรับ Onboard LED ให้ถูกต้อง เช่น ใช้ชื่อสัญลักษณ์ ARDUINO_PIN_D13 ก็สามารถดูรายละเอียดได้จากไฟล์ 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 เป็นลำดับต่อไปได้ เช่น การสร้างทาส์ก การเขียนโค้ดแบบมัลติทาสกิ้ง การประสานการทำงานและการสื่อสารระหว่างทาสก์ เป็นต้น

--

--

<rawat.s>
<rawat.s>

Written by <rawat.s>

I'm Thai and working in Bangkok/Thailand.

No responses yet