esWizardry embedded system, programming and fascinating things.

ลอง TDD บน MSP430 (Embedded C)

ช่วงนี้กำลังศึกษา TDD บนระบบสมองกลฝังตัว (Embedded system) อยู่โดย unit test framework หลักก็กำลังศึกษาอยู่ก็คือ unity และก็ค้นหาวิธีใช้งานใน google จนไปเจอ repo ใน github ของนาย jotux เข้าโดยเขาเขียน มาโครง่ายๆ ขึ้นมาสำหรับใช้เป็น test framework ของ msp430 และใช้ คอมไพเลอร์ของ IAR

ซึ่งถ้าสำหรับคนที่เริ่มต้นศึกษา TDD นี่ถือว่าเป็นตัวอย่างที่ดีมาก เพราะมันตรงไป ตรงมา ไม่มีอะไรซับซ้อน ทำเห็นเรามองภาพรวมทั้งหมดในตัวที่ใช้ทำ test ได้ เพราะหลายๆ คนอาจจะยังนึกภาพไม่ออกว่าเราจะทำ TDD และ test automation บนไมโครคอนโทรลเลอร์กันยังไง

##ครั้งแรกกับ TDD จริงๆ แล้วจะเรียก ครั้งแรกกับ TDD ก็ยังไม่ถูกนักเพราะในบล็อกนี้จะแค่ลองเล่นกับโค้ดที่เขาเขียนมาเรียบร้อยแล้วไม่ได้ลงรายละเอียดเกี่ยวกับการเขียน test เพื่อทดสอบ production code กันหรอก

##เตรียมความพร้อม ก่อนอื่นเลยให้ โคลน github repo มาไว้ที่เครื่องก่อน ในเครื่องต้องมี IAR-EW MSP430 รวมทั้งให้เพิ่มโฟลเดอร์ของ Iarbuild เข้าไปใน system path ให้เรียบร้อย

##มาลองเล่นกันเลย ! เปิด terminal ขึ้นมาแล้ว cd ไปที่ repo ที่เราโคลนมา เข้าไปที่ โฟลเดอร์ .\example\test

  • ป้อนคำสั่งเพื่อ clean project
    IarBuild.exe .\..\test\canary.ewp -clean Debug
1
2
3
4
5
6
7
8
9
PS D:\Documents\IAR4Unity\example\test> IarBuild.exe .\..\test\canary.ewp -clean Debug

     IAR Command Line Build Utility V6.6.3.2839
     Copyright 2002-2013 IAR Systems AB.

Deleting outputs for configuration Debug
Updating build tree...

8  file(s) deleted.


  • ป้อนคำสั่งเพื่อ build project
    IarBuild.exe .\..\test\canary.ewp -make Debug
1
2
3
4
5
6
7
8
9
10
11
12
13
14
PS D:\Documents\IAR4Unity\example\test> IarBuild.exe .\..\test\canary.ewp -make Debug

     IAR Command Line Build Utility V6.6.3.2839
     Copyright 2002-2013 IAR Systems AB.

Building configuration: canary - Debug
Updating build tree...
main.c
test_uart.c
Linking


Total number of errors: 0
Total number of warnings: 0


  • จากนั้นสั่งรัน test
    .\..\settings\canary.cspy.bat .\Debug\Exe\canary.d43

โดยอันนี้จะเป็นการเรียกรัน test เพื่อทดสอบกับ simulator ของ IAR เลยซึ่งก็มีข้อดีคือเราได้ทดสอบโค้ดกับสภาพแวดล้อมเสมือนจริงทำให้เราสามารถเชื่อมั่นในโค้ดของเราได้มากขึ้น ซึ่งหลายครั้งเวลาทำ TDD สำหรับระบบสมองกลฝังตัวมักจะทำการคอมไพล์และทดสอบบนเครื่องที่ใช้พัฒนาเนื่องจากมีความง่ายกว่านั่นเอง

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
PS D:\Documents\IAR4Unity\example\test> .\..\settings\canary.cspy.bat .\Debug\Exe\canary.d43

D:\Documents\IAR4Unity\example\test>"C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\common\bin\cspybat" "C:\P
rogram Files (x86)\IAR Systems\Embedded Workbench 6.5\430\bin\430proc.dll" "C:\Program Files (x86)\IAR Systems\Embedded
Workbench 6.5\430\bin\430sim.dll"  .\Debug\Exe\canary.d43 --plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbenc
h 6.5\430\bin\430bat.dll" --macro "D:\Documents\IAR4Unity\example\test\cycle_counter.mac" --backend -B "--hardware_multi
plier" "32" "--hwmult_type" "8" "-p" "D:\Documents\IAR4Unity\example\test\test_msp430fr5739.ddf" "--core=430Xv2" "--data
_model=small" "--iv_base" "0xFF90" "--odd_word_check" "-d" "sim" "--derivativeSim" "MSP430FR5739"

     IAR C-SPY Command Line Utility V6.6.3.2839
     Copyright 2000-2013 IAR Systems AB.


~~~~UNIT TESTING~~~~

Uart Suite
PASS - test_RxBufferEnqueue(test_uart.c:21)|time:0.003|
PASS - test_RxBufferEnqueue(test_uart.c:31)|time:0.004|
PASS - test_RxBufferEnqueue(test_uart.c:46)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:58)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:69)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:77)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:79)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:81)|time:0.003|

Tests run: 8
Tests Failed: 0
ALL TESTS PASSED


  • ต่อไปลองเข้าไปแก้ให้การทดสอบมันไม่ผ่านบ้างหน้าตามันจะเป็นยังไง ให้เปิดไฟล์ /example/test/unit_test/test_uart.c ขึ้นมาแก้ไขบรรทัดที่ 21

จาก

1
TEST_ASSERT("Rx buf size incorrect after buffering 1 byte",rx_size != 1);

เป็น

1
TEST_ASSERT("Rx buf size incorrect after buffering 1 byte",rx_size != 0);


จากนั้นสั่ง clean, build และรัน test อีกรอบจะเจอว่ามีกรณีที่ทดสอบไม่ผ่านอยู่

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
PS D:\Documents\IAR4Unity\example\test> IarBuild.exe .\..\test\canary.ewp -clean Debug

     IAR Command Line Build Utility V6.6.3.2839
     Copyright 2002-2013 IAR Systems AB.

Deleting outputs for configuration Debug
Updating build tree...

8  file(s) deleted.
PS D:\Documents\IAR4Unity\example\test> IarBuild.exe .\..\test\canary.ewp -make Debug

     IAR Command Line Build Utility V6.6.3.2839
     Copyright 2002-2013 IAR Systems AB.

Building configuration: canary - Debug
Updating build tree...
main.c
test_uart.c
Linking


Total number of errors: 0
Total number of warnings: 0
PS D:\Documents\IAR4Unity\example\test> .\..\settings\canary.cspy.bat .\Debug\Exe\canary.d43

D:\Documents\IAR4Unity\example\test>"C:\Program Files (x86)\IAR Systems\Embedded Workbench 6.5\common\bin\cspybat" "C:\P
rogram Files (x86)\IAR Systems\Embedded Workbench 6.5\430\bin\430proc.dll" "C:\Program Files (x86)\IAR Systems\Embedded
Workbench 6.5\430\bin\430sim.dll"  .\Debug\Exe\canary.d43 --plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbenc
h 6.5\430\bin\430bat.dll" --macro "D:\Documents\IAR4Unity\example\test\cycle_counter.mac" --backend -B "--hardware_multi
plier" "32" "--hwmult_type" "8" "-p" "D:\Documents\IAR4Unity\example\test\test_msp430fr5739.ddf" "--core=430Xv2" "--data
_model=small" "--iv_base" "0xFF90" "--odd_word_check" "-d" "sim" "--derivativeSim" "MSP430FR5739"

     IAR C-SPY Command Line Utility V6.6.3.2839
     Copyright 2000-2013 IAR Systems AB.


~~~~UNIT TESTING~~~~

Uart Suite
FAIL - test_RxBufferEnqueue(test_uart.c:21)-Rx buf size incorrect after buffering 1 byte|time:0.003|
PASS - test_RxBufferEnqueue(test_uart.c:31)|time:0.004|
PASS - test_RxBufferEnqueue(test_uart.c:46)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:58)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:69)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:77)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:79)|time:0.003|
PASS - test_RxBufferDequeue(test_uart.c:81)|time:0.003|

Tests run: 8
Tests Failed: 1
PS D:\Documents\IAR4Unity\example\test>


ซึ่งเวลาที่มีกรณีทดสอบไม่ผ่านก็จะมีข้อความบอกรายละเอียดเพิ่มเติมตามรูปแบบของมาโครที่ได้ออกแบบไว้

1
FAIL - test_RxBufferEnqueue(test_uart.c:21)-Rx buf size incorrect after buffering 1 byte|time:0.003|


ด้านล่างนี้คือโค้ดบางส่วนของ TEST_ASSERT มาโครที่ใช้สำหรับทดสอบจะเห็นได้ว่ามีโค้ดแค่นิดเดียวเองซึ่งถึงแม้ว่าจะเป็นมือใหม่ก็สามารถทำความเข้าใจและปรับปรุงให้เป็น test framework ในแบบที่เราต้องการได้

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define PRINT_PASS()     printf("PASS - %s(%s:%d)",__FUNCTION__,__FILE__,__LINE__)
#define PRINT_FAIL(m)    printf("FAIL - %s(%s:%d)-%s",__FUNCTION__,__FILE__,__LINE__,m)

#define TEST_ASSERT(message, test)  \
    do                              \
    {                               \
        if (test)                   \
        {                           \
            tests_failed++;         \
            PRINT_FAIL(message);    \
        }                           \
        else                        \
        {                           \
            PRINT_PASS();           \
        }                           \
        tests_run++;                \
        printf("|time:%.3f|\n",(float)((_cycle_cnt - _cycle_start))/16000000); \
        _cycle_start = _cycle_cnt;  \
    } while (0)


…<3