CI สำหรับเฟิร์มแวร์
เป้าหมาย
หัวข้อที่มีชื่อว่า “เป้าหมาย”เมื่อจบบทเรียนนี้ คุณจะ
- เขียน workflow ของ GitHub Actions ที่รัน unit test บนเครื่องโฮสต์ทุก pull request
- เพิ่มขั้นตรวจรูปแบบโค้ดด้วย clang-format และวิเคราะห์แบบสถิตด้วย cppcheck
- อธิบายว่าอะไรที่ CI บน runner สาธารณะตรวจได้ และอะไรที่ต้องทดสอบบนบอร์ดจริง
ใช้เวลาประมาณ 70 นาที (แนวคิด 15 · ฝึก 25 · แล็บ 25 · เช็ก 5) ต้องมีทุกอย่างจากบทเรียน 6.1 และ python3
ถ้าจะรันครบทุกขั้นในเครื่อง ต้องมี cppcheck และ gcc-arm-none-eabi ด้วย (บน Ubuntu: sudo apt-get install cppcheck gcc-arm-none-eabi)
แล็บต้องมีบัญชี GitHub
ก่อนเริ่ม
หัวข้อที่มีชื่อว่า “ก่อนเริ่ม”ทวนสองข้อ
- hook
pre-commitของบทเรียน 2.3 ตรวจทุก commit ในเครื่องคุณ ทำไมมันยังไม่พอสำหรับทีม (คำใบ้:git commit --no-verify) - บทเรียน 6.1 บอกว่า test ที่ผ่านพิสูจน์อะไรได้บ้าง และพิสูจน์ด้วยวิธีไหนว่ามันล้มเป็น
ดูของจริงก่อน
หัวข้อที่มีชื่อว่า “ดูของจริงก่อน”repo ของ SDK ที่หลักสูตรนี้ใช้มี workflow ของ GitHub Actions อยู่ไฟล์เดียวที่ commit ef72c1b ข้างล่างคือส่วนหัวกับขั้นแรกของมัน
on: release: types: [published] workflow_dispatch:
permissions: contents: read# ... (concurrency และ env ละไว้)jobs: notify: runs-on: ubuntu-latest steps: - name: Ask the relay to re-read GitHub run: | set -euo pipefail echo "POST $RELAY/api/firmware/github/refresh" code=$(curl -s -o /tmp/refresh.json -w '%{http_code}' -X POST --max-time 120 \ "$RELAY/api/firmware/github/refresh") echo "HTTP $code"; cat /tmp/refresh.json; echo test "$code" = "200"ที่มา: .github/workflows/notify-flash-relay.yml บรรทัด 20-46 (Apache-2.0, tesaiot-pse84-devkit-sdk)
ทายก่อนอ่านต่อ สามข้อ workflow นี้รันเมื่อไร มัน build เฟิร์มแวร์ไหม และถ้า curl ได้ HTTP 500 ขั้นนี้จะเขียวหรือแดง
คำตอบ: รันเมื่อมีการเผยแพร่ release (หรือกดรันเอง) มัน ไม่ได้ build เฟิร์มแวร์ แค่บอก relay ของ Remote Flash ให้ดึง release ใหม่
แล้วขั้นถัดไปของไฟล์เดียวกันตรวจด้วย sha256 ว่าไฟล์ .hex ไปถึงจริง (“Firing the refresh is not the same as the file arriving”)
ถ้าได้ 500 บรรทัดสุดท้าย test "$code" = "200" คืนค่าไม่ใช่ 0 ขั้นนี้จึงแดง บรรทัดนั้นคือสิ่งที่ทำให้ขั้นนี้ล้มเป็น ถ้าไม่มีมัน echo ข้างบนจะพิมพ์ 500 แล้วจบด้วย 0
บทเรียนนี้ใช้หลักเดียวกันกับทุกการตรวจ
1. workflow, job, step และ “workflow บาง สคริปต์หนา”
หัวข้อที่มีชื่อว่า “1. workflow, job, step และ “workflow บาง สคริปต์หนา””GitHub Actions อ่านไฟล์ YAML จาก .github/workflows/ ของ repo ศัพท์สามคำที่ต้องแยกให้ออก
| คำ | คืออะไร | ในไฟล์ |
|---|---|---|
| workflow | ไฟล์หนึ่งไฟล์ ถูกปลุกด้วยเหตุการณ์ เช่น pull_request หรือ push |
on: |
| job | งานหนึ่งชิ้นบนเครื่องเสมือนใหม่ของตัวเอง job ต่างกันรันขนานกันได้และไม่เห็นไฟล์ของกัน | jobs.<ชื่อ>.runs-on |
| step | คำสั่งหนึ่งขั้นใน job ขั้นที่คืนค่าไม่ใช่ 0 ทำให้ job ล้ม | steps: ที่มี uses: (action สำเร็จรูป) หรือ run: (คำสั่ง shell) |
ข้อตกลงสามข้อที่ใช้ตลอดบทนี้
- workflow บาง สคริปต์หนา ใส่คำสั่งตรวจจริงไว้ใน ci.sh ใน repo แล้วให้ workflow แค่ติดตั้งเครื่องมือกับเรียก
bash ci.sh <ขั้น>คุณรันคำสั่งเดียวกันทุกตัวอักษรในเครื่องได้ก่อน push ไม่ต้องรอ CI เพื่อรู้ผล - สิทธิ์น้อยที่สุด เอกสาร GitHub แนะนำว่า “It’s good security practice to set the default permission for the
GITHUB_TOKENto read access only for repository contents” คือpermissions: contents: readแบบเดียวกับ workflow ของ SDK ข้างบน และเมื่อระบุสิทธิ์ข้อใดข้อหนึ่ง สิทธิ์ที่ไม่ได้ระบุจะเป็นnone - ล็อกทุกอย่างที่เปลี่ยนเองได้ tag อย่าง
v7ของ action ถูกย้ายไปชี้ commit อื่นได้ เอกสาร GitHub ระบุว่า “Pinning an action to a full-length commit SHA is currently the only way to use an action as an immutable release” ป้ายชื่อ runner แบบubuntu-latestก็ย้ายได้ (runner-images บอกว่ามัน “point towards the newest stable OS version available”) ซึ่งเปลี่ยนรุ่นของ cppcheck และคอมไพเลอร์ที่ apt ให้ บทนี้จึงใช้ubuntu-24.04และตั้งtimeout-minutesเพราะถ้าไม่ตั้ง job ที่ค้างจะรันได้ถึง 360 นาที
2. การตรวจสี่ขั้น และทำให้ทุกขั้นล้มเป็น
หัวข้อที่มีชื่อว่า “2. การตรวจสี่ขั้น และทำให้ทุกขั้นล้มเป็น”| ขั้น | เครื่องมือ | จับอะไรได้ |
|---|---|---|
tests |
Unity + prove_red.sh จากบทเรียน 6.1 |
ตรรกะผิด และ test ที่ไม่ได้ทดสอบอะไร |
format |
clang-format 18.1.3 กับ .clang-format | โค้ดที่จัดรูปแบบต่างจากที่ทีมตกลง ทำให้ diff ของ pull request อ่านง่ายขึ้น |
static |
cppcheck | บั๊กที่เห็นได้โดยไม่ต้องรัน เช่นเขียนเลยขอบอาร์เรย์ |
cross |
arm-none-eabi-gcc สำหรับ Cortex-M33 และ Cortex-M55 | โค้ดที่คอมไพล์ได้บนคอมพิวเตอร์แต่ไม่ได้บนไมโครคอนโทรลเลอร์ |
กับดักที่พบบ่อยที่สุดของ CI คือ ขั้นที่รายงานปัญหาแต่ยังเขียว เราทดลองกับเครื่องมือทั้งสองรุ่นที่บทนี้ใช้ ได้ผลตรงกัน
clang-format --dry-runเจอโค้ดที่จัดรูปแบบผิด พิมพ์คำเตือน แล้วคืน 0 ต้องเติม--Werrorจึงคืน 1cppcheckเจอarrayIndexOutOfBoundsพิมพ์error:แล้วคืน 0 ต้องเติม--error-exitcode=1- คำสั่งที่ต่อท้ายด้วย
|| trueหรือ step ที่ตั้งcontinue-on-error: trueเขียวเสมอ ไม่ว่าข้างในจะเกิดอะไร - ใน bash
( ขั้นตอน ) || rc=$?ปิดset -eของทุกคำสั่งใน subshell คำสั่งที่ล้มกลางทางจะถูกข้ามแล้วจบด้วย 0 (ci.sh มีบันทึกไว้ในฟังก์ชันrun_stage)
ขั้น cross ใช้แฟล็กของ Cortex-M33 ตาม Makefile ของไลบรารีในแม่แบบของ SDK
# Toolchain (same as project)GCC_PATH := /Applications/mtb-gcc-arm-eabi/14.2.1/gcc/binCC := $(GCC_PATH)/arm-none-eabi-gccAR := $(GCC_PATH)/arm-none-eabi-ar
# Compiler flags for PSoC Edge Cortex-M33 (MUST match project: softfp)CFLAGS := -mcpu=cortex-m33 -mthumb -mfloat-abi=softfp -mfpu=fpv5-sp-d16ที่มา: bento_libs/claw/kit-pse84-ai/tesaiot/Makefile บรรทัด 25-31 (Apache-2.0, tesaiot-pse84-devkit-sdk)
สังเกต GCC_PATH ที่ชี้โฟลเดอร์บน macOS ของเครื่องหนึ่ง บน runner ของ CI บรรทัดนี้ใช้ไม่ได้ทันที CI จึงช่วยหาสมมติฐานเกี่ยวกับเครื่องที่ซ่อนอยู่แบบนี้ได้
และคอมไพเลอร์ของ ModusToolbox ในบรรทัดนั้นคือ GCC 14.2.1 ส่วน gcc-arm-none-eabi จาก apt ของ Ubuntu 24.04 คือ 13.2.1 ขั้น cross จึงตรวจว่าตรรกะ คอมไพล์ได้ สำหรับ CPU ของบอร์ด
ไม่ได้สร้างไบนารีเดียวกับที่ build จริง
3. CI บน runner สาธารณะตรวจอะไรได้ และอะไรต้องใช้บอร์ด
หัวข้อที่มีชื่อว่า “3. CI บน runner สาธารณะตรวจอะไรได้ และอะไรต้องใช้บอร์ด”| CI บน runner สาธารณะตรวจได้ | ต้องใช้บอร์ดจริง |
|---|---|
| ตรรกะที่อยู่หลังตะเข็บ (บทเรียน 6.1) | timing ของ interrupt และตัวตั้งเวลา (บทเรียน 4.1, 4.2) |
| รูปแบบโค้ดและบั๊กที่วิเคราะห์ได้แบบสถิต | cache กับ DMA และลำดับของ barrier (บทเรียน 4.4) test บนคอมพิวเตอร์ของบทนั้นจำลองได้ แต่พิสูจน์ไม่ได้ |
| ตรรกะคอมไพล์ได้สำหรับ Cortex-M33 และ Cortex-M55 | สัญญาณจริงบนบัส UART, I2C, SPI (โมดูล 5) |
| ไฟล์ที่ไม่ควรเข้า repo เช่นที่ hook ของบทเรียน 2.3 ตรวจ | watchdog รีเซ็ตจริง และบอร์ดบูตขึ้นหลังถอดสายเสียบใหม่ (บทเรียน 4.3, 2.1) |
ทำไมไม่ build เฟิร์มแวร์ทั้งก้อนใน CI เลย Makefile เดียวกันบอกเหตุผลข้อหนึ่งไว้ตรง ๆ
“Source files (tesaiot_*.c) are proprietary” และแจก libtesaiot.a ที่ build แล้วให้แทน
(บรรทัด 10-11)
ส่วน git repo ของ SDK เองก็ไม่มีไฟล์ .a เพราะ .gitignore ตัดทิ้ง บทเรียน 2.1 จึงให้ build จากไฟล์ zip ของ release
build เต็มจึงต้องใช้ ModusToolbox ที่ติดตั้งครบกับแพ็กเกจของ release ซึ่งทำบนเครื่องของคุณตาม บทเรียน 2.1
และ ขั้นตอน build และ flash ของหลักสูตรเฟิร์มแวร์ TESAIoT
ทางต่อบอร์ดเข้ากับ CI คือ self-hosted runner ที่มีบอร์ดเสียบอยู่ (hardware-in-the-loop) แต่เอกสาร GitHub เตือนว่า “Self-hosted runners should almost never be used for public repositories on GitHub, because any user can open pull requests against the repository and compromise the environment” repo สาธารณะจึงควรเก็บการทดสอบบนบอร์ดไว้ใน repo ส่วนตัวหรือทำด้วยมือ แล้วบันทึกหลักฐานไว้
ตัวอย่างสมบูรณ์
หัวข้อที่มีชื่อว่า “ตัวอย่างสมบูรณ์”โฟลเดอร์ examples/ มีห้าไฟล์
- host-tests.yml workflow ที่เล็กที่สุดที่ใช้ได้จริง job เดียว รัน test ของบทเรียน 6.1 ความเห็นในไฟล์อธิบาย workflow, job และ step
- ci.sh การตรวจสี่ขั้น ทุกขั้นจบด้วย
PASS,FAILหรือNOT CHECKED(เครื่องมือไม่มี หรือไม่มีไฟล์ให้ตรวจ) และNOT CHECKEDคืนค่าที่ไม่ใช่ 0 เหมือนFAIL - .clang-format รูปแบบโค้ดของหลักสูตร ไฟล์ C ของบทเรียน 6.1 จัดรูปแบบด้วยไฟล์นี้แล้ว
- check_workflow.py ตรวจโครงของ workflow สี่ job ตามกติกาของบทนี้ในเครื่อง (ไม่ได้รัน workflow จริง)
- .gitignore กัน
.venv/ที่สร้างตอนฝึก
รันทั้งสี่ขั้นกับโค้ดของบทเรียน 6.1 ในเครื่อง (ต้อง clone Unity ไว้ใน examples/unity ของบทเรียน 6.1 ก่อน)
cd examplespython3 -m venv .venv.venv/bin/pip install clang-format==18.1.3 pyyaml==6.0.3SRC_DIR=../../l01-unit-tests-on-host/examples TEST=../solution/test_level_alarm.c \ CLANG_FORMAT=.venv/bin/clang-format bash ci.sh allผลที่เราได้คือ tests, format, static และ cross ขึ้น PASS ทั้งสี่ขั้น ถ้าเครื่องคุณไม่มี cppcheck ขั้น static จะขึ้น NOT CHECKED และคำสั่งจบด้วยค่าที่ไม่ใช่ 0 ซึ่งถูกต้อง
ลองทำให้แต่ละขั้นแดง แล้วทายก่อนรัน ทำในสำเนาของโฟลเดอร์ตัวอย่าง 6.1 ไม่ใช่ไฟล์จริง
formatลบช่องว่างรอบ=ในบรรทัดa->count = 0u;หนึ่งบรรทัดstaticเพิ่มฟังก์ชันที่วนfor (int i = 0; i <= 4; i++)เขียนลงint history[4]crossเพิ่ม_Static_assert(sizeof(long) == 8, "assumes a 64-bit long");ใต้#includeขั้นtestsยังผ่าน เพราะlongบนคอมพิวเตอร์ 64 บิตยาว 8 ไบต์ แต่crossแดง เพราะบน Cortex-M ยาว 4 ไบต์ ขนาดของชนิดข้อมูลขึ้นกับสถาปัตยกรรม (บทเรียน 1.1)testsใช้TEST=test_level_alarm_first.ctest ทั้งสองข้อผ่าน แต่ขั้นนี้แดง เพราะprove_red.shพบบั๊กที่รอด
ฝึกเติม
หัวข้อที่มีชื่อว่า “ฝึกเติม”เปิด practice/firmware-ci.yml job tests ให้มาแล้ว มีช่องให้เติม 6 จุด มากกว่าบทก่อนตามจังหวะของโมดูล
- รันกับทุก pull request ด้วย
- จำกัดสิทธิ์ของ
GITHUB_TOKENให้อ่านได้อย่างเดียว - ล็อก action ทุกตัวด้วย commit SHA เต็ม
- job
formatติดตั้ง clang-format รุ่นที่ล็อกไว้ แล้วรันbash ci.sh format - job
static-analysisติดตั้ง cppcheck แล้วรันbash ci.sh static - job
cross-compileติดตั้ง gcc-arm-none-eabi แล้วรันbash ci.sh cross
ตรวจในเครื่องก่อน push
cd examples.venv/bin/python check_workflow.py ../practice/firmware-ci.ymlก่อนเติม ตัวตรวจขึ้น 10 failed งานจะเสร็จเมื่อขึ้น 0 failed ตัวตรวจนี้จับ || true และ continue-on-error ด้วย ลองใส่ดูแล้วดูมันแดง
ลองเองก่อนอย่างน้อย 15 นาที แล้วเปิด solution/firmware-ci.yml เราตรวจเฉลยแล้วว่าตัวตรวจขึ้น 21 passed, 0 failed
สิ่งที่ควรเทียบ
- job
formatติดตั้ง clang-format ด้วย pip ที่รุ่น 18.1.3 แทนตัวที่มากับ runner เพราะ image ของubuntu-24.04มี clang-format สามรุ่น (16.0.6, 17.0.6, 18.1.3 ตาม รายการของ image รุ่น 20260920) และรุ่นต่างกันจัดรูปแบบต่างกันได้ pip ให้รุ่นเดียวกันทั้งบน runner บน Windows และบน macOS concurrencyที่cancel-in-progress: trueยกเลิกรอบเก่าเมื่อ push ใหม่เข้า pull request เดิม ขณะที่ workflow ของ SDK ตั้งfalseให้รอบที่เริ่มแล้วทำจนจบ ค่าที่ถูกขึ้นกับงาน: การตรวจโค้ดรอบเก่าไม่มีประโยชน์เมื่อมีโค้ดใหม่ แต่การแจ้งเตือนที่ถูกยกเลิกกลางทางอาจไม่ถึงปลายทาง
เช็กความเข้าใจ
หัวข้อที่มีชื่อว่า “เช็กความเข้าใจ”ตอบคำถาม 5 ข้อใน quiz.yaml (บนเว็บไซต์อยู่ท้ายหน้านี้) ครอบคลุมเป้าหมายทั้งสามข้อ ตอบถูกตั้งแต่ 4 ข้อขึ้นไปถือว่าจบบทเรียน
งาน: ให้ GitHub ตรวจงานของคุณทุก pull request แล้วพิสูจน์ว่ามันแดงเป็น
- สร้าง repo ของคุณเอง (ส่วนตัวหรือสาธารณะก็ได้) วางไฟล์ตามโครงนี้
ci.shและ.clang-formatจากบทนี้ไว้ที่ราก, โฟลเดอร์host-tests/ที่มีไฟล์จากexamples/ของบทเรียน 6.1 (ยกเว้นunity/และbuild/) พร้อมtest_level_alarm.cที่คุณเติมครบแล้ว และ workflow ที่คุณเขียนไว้ที่.github/workflows/firmware-ci.yml(ถ้าทำแล็บของบทเรียน 6.1 ด้วยตรรกะของคุณเอง ใช้ของคุณได้ ปรับชื่อไฟล์ในprove_red.shให้ตรง) - push แล้วเปิดแท็บ Actions ทั้งสี่ job ต้องเขียว
- เปิด pull request ที่ใส่บั๊กหนึ่งจุดจากหัวข้อตัวอย่างสมบูรณ์ ดู job ที่ควรแดงว่าแดงจริง แล้วปิด pull request นั้นโดยไม่ merge
- ย้ายการตรวจหนึ่งอย่างจาก hook
pre-commitของบทเรียน 2.3 มาเป็นขั้นในci.shแล้วพิสูจน์ด้วย pull request ว่า--no-verifyข้ามมันไม่ได้อีก - ถ้ามีบอร์ด เขียนสั้น ๆ ว่าการเปลี่ยนแปลงแบบไหนใน repo นี้ที่ CI เขียวแล้วคุณยังต้อง flash ลงบอร์ดเพื่อตรวจ และตรวจอะไร
หลักฐานที่เก็บไว้ใน portfolio: ลิงก์ของ repo ภาพหรือลิงก์ของรอบที่เขียวครบ ลิงก์ของ pull request ที่แดง พร้อมบอกว่าบั๊กคืออะไรและ job ไหนจับได้ และคำตอบของข้อ 5
- อ่าน workflow ของ SDK ทั้งไฟล์ notify-flash-relay.yml
ขั้นที่สองตรวจอะไร และทำไมผู้เขียนแยกมันออกจาก workflow อื่นที่รันเมื่อมี release เหมือนกัน
(ความเห็นหัวไฟล์อ้างถึง
firmware-index.ymlซึ่งไม่มีใน commit นี้ แต่เหตุผลอยู่ในความเห็นครบ) - ลองเปิด
--enable=styleของ cppcheck กับโค้ดของคุณ ข้อความไหนมีประโยชน์ ข้อไหนควรปิดด้วย// cppcheck-suppressพร้อมเหตุผล
จบโมดูล 6 และจบหลักสูตรนี้แล้ว กลับไปดู Checkpoint ท้ายโมดูล และ หน้าหลักสูตร หลักสูตรต่อไปที่ใช้ทุกอย่างจากที่นี่คือ หลักสูตรเฟิร์มแวร์ TESAIoT
สะท้อนคิด
หัวข้อที่มีชื่อว่า “สะท้อนคิด”- ถ้า CI เขียวทุกรอบมาหกเดือน คุณจะรู้ได้อย่างไรว่ามันยังตรวจอะไรอยู่
- ส่วนไหนของงานคุณที่ยังพึ่ง “เครื่องของฉันผ่าน” และต้องทำอะไรจึงย้ายมันเข้า CI ได้
แหล่งอ้างอิง
หัวข้อที่มีชื่อว่า “แหล่งอ้างอิง”- GitHub Actions documentation
- ClangFormat
- Cppcheck
- GitHub Docs: Security hardening for GitHub Actions
- GitHub Docs: Workflow syntax
- actions/runner-images
คำถามทบทวน
ลองตอบเองก่อน แล้วค่อยเปิดดูเฉลย
-
ทีมตกลงให้ทุก pull request ผ่าน unit test ก่อน merge ส่วนใดของ workflow ที่ทำให้ GitHub รันมันเมื่อมีคนเปิดหรือ push เข้า pull request (เป้าหมายข้อ 1)
- pull_request ใต้ on:
- runs-on: ubuntu-24.04
- permissions: contents: read
- timeout-minutes: 10
ดูเฉลย
คำตอบ: A. pull_request ใต้ on:
on: บอกว่าเหตุการณ์ใดปลุก workflow runs-on เลือกเครื่อง permissions จำกัดสิทธิ์ของ token และ timeout-minutes จำกัดเวลา ไม่มีข้อไหนนอกจาก on: ที่กำหนดว่าจะรันเมื่อไร
-
ข้อใดทำให้ workflow ให้ผลเหมือนเดิมเมื่อรันซ้ำในอีกหลายเดือน (เลือกได้หลายข้อ) (เป้าหมายข้อ 1)
- ล็อก action ด้วย commit SHA เต็ม 40 ตัว แทน tag อย่าง v7
- ใช้ runs-on: ubuntu-24.04 แทน ubuntu-latest
- ติดตั้ง clang-format ด้วย pip ที่รุ่น 18.1.3
- ใช้ ubuntu-latest เพื่อให้ได้เครื่องมือรุ่นใหม่เสมอ
ดูเฉลย
คำตอบ: A. ล็อก action ด้วย commit SHA เต็ม 40 ตัว แทน tag อย่าง v7 · B. ใช้ runs-on: ubuntu-24.04 แทน ubuntu-latest · C. ติดตั้ง clang-format ด้วย pip ที่รุ่น 18.1.3
tag ของ action ย้ายได้ และเอกสาร GitHub ระบุว่าการล็อกด้วย SHA เต็มเป็นทางเดียวที่ได้รุ่นที่ไม่เปลี่ยน ubuntu-latest ชี้รุ่นล่าสุดของระบบปฏิบัติการ จึงเปลี่ยนรุ่นของเครื่องมือที่ apt ให้ได้ ส่วน clang-format รุ่นต่างกันจัดรูปแบบต่างกันได้
-
ขั้น format ของ CI รัน clang-format --dry-run กับไฟล์ที่จัดรูปแบบผิด log มีคำเตือน แต่ job เขียว สาเหตุที่น่าจะเป็นที่สุดคืออะไร (เป้าหมายข้อ 2)
- ขาด --Werror จึงพิมพ์คำเตือนแต่คืน 0
- runner ไม่มี clang-format
- ไฟล์ .clang-format เสีย
- GitHub ไม่อ่านค่าที่คืนจาก step
ดูเฉลย
คำตอบ: A. ขาด --Werror จึงพิมพ์คำเตือนแต่คืน 0
เราทดลองกับ clang-format 18.1.3 แล้ว --dry-run อย่างเดียวคืน 0 แม้เจอโค้ดที่จัดรูปแบบผิด ต้องเติม --Werror จึงคืน 1 ถ้าไม่มีเครื่องมือหรือ config เสีย จะคืนค่าที่ไม่ใช่ 0 และ job จะแดง
-
ข้อใดทำให้ขั้นตรวจใน CI เขียวได้แม้เครื่องมือพบปัญหา (เลือกได้หลายข้อ) (เป้าหมายข้อ 2)
- cppcheck ที่ไม่มี --error-exitcode
- ต่อท้ายคำสั่งด้วย || true
- ตั้ง continue-on-error: true ให้ step
- ล็อก action ด้วย commit SHA
ดูเฉลย
คำตอบ: A. cppcheck ที่ไม่มี --error-exitcode · B. ต่อท้ายคำสั่งด้วย || true · C. ตั้ง continue-on-error: true ให้ step
cppcheck พิมพ์ error แต่คืน 0 ถ้าไม่ระบุ --error-exitcode ส่วน || true และ continue-on-error กลืนความล้มเหลวทั้งหมด การล็อก SHA ไม่เกี่ยวกับผลของการตรวจ วิธีจับคือจงใจใส่บั๊กแล้วดูให้ขั้นนั้นแดง แบบเดียวกับบทเรียน 6.1
-
CI บน runner สาธารณะเขียวครบทั้งสี่ขั้น ข้อใดยังต้องตรวจบนบอร์ดจริง (เลือกได้หลายข้อ) (เป้าหมายข้อ 3)
- ข้อมูลที่ DMA เขียนแล้ว CPU อ่านผ่าน cache ถูกต้อง
- watchdog รีเซ็ตบอร์ดจริงเมื่องานค้าง
- ตรรกะของ state machine เปลี่ยนสถานะเมื่อค่าถึงเกณฑ์พอดี
- ไฟล์ C คอมไพล์ได้สำหรับ Cortex-M33
ดูเฉลย
คำตอบ: A. ข้อมูลที่ DMA เขียนแล้ว CPU อ่านผ่าน cache ถูกต้อง · B. watchdog รีเซ็ตบอร์ดจริงเมื่องานค้าง
cache กับ DMA และการรีเซ็ตของ watchdog เกิดในฮาร์ดแวร์ test บนคอมพิวเตอร์จำลองได้แต่พิสูจน์ไม่ได้ ส่วนตรรกะของ state machine ตรวจด้วย unit test และการคอมไพล์สำหรับ Cortex-M33 ตรวจด้วยขั้น cross บน runner ได้แล้ว
อ้างอิงบทเรียนนี้
ถ้านำบทเรียนนี้ไปสอน ทำสไลด์ หรือทำเอกสารต่อ ให้อ้างอิงด้วยข้อความนี้ ถ้าดัดแปลงเนื้อหา ให้เติม (ดัดแปลง)ต่อท้ายชื่อบทเรียน
"CI สำหรับเฟิร์มแวร์" จาก TESA Open Knowledge โดยสมาคมสมองกลฝังตัวไทย (Thai Embedded Systems Association: TESA) https://github.com/tesaiot/tesa-qualification-program สัญญาอนุญาต CC BY-NC 4.0
ข้อความอ้างอิงภาษาอังกฤษ: "CI for firmware" from TESA Open Knowledge by the Thai Embedded Systems Association (TESA), https://github.com/tesaiot/tesa-qualification-program, licensed under CC BY-NC 4.0
ลิงก์บทเรียน: https://tesaiot.github.io/tesa-qualification-program/courses/embedded-c-foundations/m06-test-and-ci/l02-ci-for-firmware/
บทเรียนนี้ดัดแปลงจากต้นฉบับด้านล่าง เมื่ออ้างอิงให้คงเครดิตต้นฉบับไว้ด้วย
https://github.com/tesaiot/tesaiot-pse84-devkit-sdk/tree/ef72c1b658178eee8c38b1e47d28b006f80a59b5 · SDK examples and docs are linked at this commit, not copied into this course. Lessons quote short excerpts (at most 25 lines) with a link to the file at this commit and the credit (Apache-2.0, tesaiot-pse84-devkit-sdk).
TESA Open Knowledge · © 2026 สมาคมสมองกลฝังตัวไทย (TESA) · CC BY-NC 4.0
เนื้อหาเผยแพร่ภายใต้ CC BY-NC 4.0 นำไปใช้ต่อในงานที่ไม่ใช่เพื่อการค้าได้ โปรดอ้างอิงสมาคมสมองกลฝังตัวไทย (TESA) ทุกครั้ง · วิธีอ้างอิง TESA