> For the complete documentation index, see [llms.txt](https://docs.aic-eec.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aic-eec.com/interfacing-with-infineon-psoc-tm-edge/basic-mcu-interfacing/c-in-modustoolbox-mtb.md).

# C in ModusToolBox (MTB)

## 1. โครงสร้างโปรแกรม C ใน ModusToolbox

### <mark style="color:blue;">1.1 Header Files และ Include</mark>

การจัดการ `#include` ให้เป็นระบบเป็นพื้นฐานที่สำคัญมากในการเขียน Embedded C\
โดยเฉพาะบน **Infineon PSoC™ Edge E84** ที่ใช้ ModusToolbox ซึ่งมีทั้ง HAL, BSP และ Peripheral Driver Library (PDL)

การจัดกลุ่ม header ที่ดี จะช่วยให้:

* โค้ดอ่านง่ายและดูเป็นมืออาชีพ
* ลดการพึ่งพาไฟล์ที่ไม่จำเป็น
* ลดโอกาสเกิดปัญหา compile และ dependency ที่ซับซ้อนในอนาคต

***

{% hint style="info" %}

#### แนวคิด (Concept)

ใน ModusToolbox ควรแบ่ง `#include` ออกเป็น **2 กลุ่มหลัก** อย่างชัดเจน:

1. **System headers**\
   เป็น header จาก C standard library ใช้กับภาษา C ทั่วไป
2. **Infineon / PSoC platform headers**\
   เป็น header ที่เกี่ยวข้องกับ hardware, board และ middleware ของ Infineon

การเรียงลำดับที่แนะนำคือ\
👉 *System headers ก่อน* → *Platform headers ตามหลัง*
{% endhint %}

***

#### ตัวอย่างโครงสร้าง `#include` ที่แนะนำ

```c
/* ===================== System headers ===================== */
#include <stdio.h>      /* printf */
#include <stdint.h>     /* uint32_t, int16_t */
#include <stdbool.h>    /* bool, true, false */
#include <string.h>     /* memcpy, strlen */

/* ================= Infineon / PSoC headers ================= */
#include "cy_pdl.h"         /* Peripheral Driver Library */
#include "cyhal.h"          /* Hardware Abstraction Layer */
#include "cybsp.h"          /* Board Support Package */
#include "cy_retarget_io.h" /* UART printf redirection */
```

***

#### Best Practice

* Include เฉพาะ header ที่ใช้งานจริงเท่านั้น
* แยกกลุ่ม System กับ Platform ให้ชัดเจนเสมอ
* อย่า include header ซ้ำซ้อนโดยไม่จำเป็น
* หลีกเลี่ยงการ include header ใน `.h` ถ้าไม่จำเป็น (ควร include ใน `.c` แทน)

***

{% hint style="warning" %}

#### **ข้อควรระวัง (Pitfall)**

* การ include header จำนวนมากเกินไป อาจทำให้
  * compile time เพิ่มขึ้น
  * dependency ซับซ้อน
  * เกิด warning หรือ error ที่ debug ยาก
* การ include header ในลำดับที่ไม่เหมาะสม อาจทำให้ macro หรือ type ชนกันได้
  {% endhint %}

***

#### 📘 MISRA-C Note (สำหรับงานอุตสาหกรรม)

* MISRA-C แนะนำให้ include header เท่าที่จำเป็นเท่านั้น
* Header ควรมี include guard หรือ `#pragma once`
* หลีกเลี่ยงการ include header ที่มี side effect (เช่น มี code execution)

***

**สรุปสั้น ๆ**

> การจัด `#include` ที่ดี คือจุดเริ่มต้นของ firmware ที่ดูแลรักษาง่าย และขยายต่อได้ในระยะยาว

### <mark style="color:blue;">1.2 Simple Define (</mark><mark style="color:blue;">`#define`</mark> <mark style="color:blue;"></mark><mark style="color:blue;">สำหรับค่าคงที่)</mark>

การใช้ `#define` สำหรับกำหนดค่าคงที่ (constant) เป็นสิ่งที่พบได้บ่อยมากในงาน Embedded C\
โดยเฉพาะบน **PSoC™ Edge E84** ที่ต้องจัดการกับ GPIO, communication, sensor และ hardware configuration จำนวนมาก

หากใช้ `#define` อย่างเป็นระบบ จะช่วยให้โค้ด:

* อ่านง่าย
* แก้ไขง่าย
* ลด bug จากการใช้ magic number

***

{% hint style="info" %}

#### แนวคิด (Concept)

`#define` เหมาะสำหรับ:

* ค่าคงที่ที่ **ไม่เปลี่ยนระหว่าง runtime**
* ค่า configuration ที่เกี่ยวข้องกับ hardware
* ค่า parameter ที่ต้องใช้ซ้ำหลายจุดในโค้ด

ชื่อของ macro ควร:

* ใช้ **ตัวพิมพ์ใหญ่ทั้งหมด**
* ใช้ `_` คั่นคำ
* สื่อความหมายชัดเจน
  {% endhint %}

***

#### ตัวอย่าง Simple Define พื้นฐาน

**GPIO Pin Configuration**

(ตัวอย่างจาก hello-world project)

```c
#define LED_PIN        CYBSP_USER_LED
#define BUTTON_PIN     CYBSP_USER_BTN
```

***

**Communication Settings**

```c
#define UART_BAUDRATE  115200
#define I2C_FREQUENCY  400000U   /* 400 kHz */
```

***

**Sensor Configuration**

(ตัวอย่างจาก BMI270 driver)

```c
#define SAMPLE_RATE_HZ    100
#define IMU_I2C_ADDRESS  0x68
#define BUFFER_SIZE      256
```

***

**Application Constants**

```c
#define MAX_RETRIES       3
#define TIMEOUT_MS        5000
#define LED_BLINK_DELAY   500
```

***

#### ตัวอย่างจากโค้ดจริงของ Infineon

**จาก `ml-deepcraft-data-collection`**

```c
#define MAX_FRAMES_IN_CHUNK   (8U)      /* 400Hz / 8 = 50Hz */
#define AXIS_COUNT            (3U)      /* X, Y, Z */
#define SENSOR_COUNT          (2U)      /* Accel, Gyro */
#define GRAVITY_EARTH         (9.80665f)/* m/s^2 */
```

***

**Accelerometer Ranges (BMI270)**

```c
#define IMU_ACC_RANGE_2G      0x4000
#define IMU_ACC_RANGE_4G      0x2000
#define IMU_ACC_RANGE_8G      0x1000
#define IMU_ACC_RANGE_16G     0x0800
```

***

**Gyroscope Conversion Factors**

```c
#define IMU_GYRO_DIVIDE_125   262.0f   /* ±125 dps */
#define IMU_GYRO_DIVIDE_250   131.0f   /* ±250 dps */
#define IMU_GYRO_DIVIDE_500   65.5f    /* ±500 dps */
```

***

**ตัวอย่างจาก `wifi-udp-server`**

```c
#define UDP_LED_CMD_LEN          (1U)
#define LED_ON_CMD               ('1')
#define LED_OFF_CMD              ('0')
#define MAX_UDP_RECV_BUFFER_SIZE (20U)

#define SHIFT_BIT_8              (8U)
#define SHIFT_BIT_16             (16U)
#define SHIFT_BIT_24             (24U)

#define APP_SDIO_FREQUENCY_HZ    (25000000U) /* 25 MHz */
#define SDHC_SDIO_64BYTES_BLOCK  (64U)
```

***

#### Best Practice

* ใช้ `U`, `UL`, `f` ให้เหมาะกับชนิดข้อมูล (type)
* หลีกเลี่ยง magic number ในโค้ด
* ใช้ชื่อ macro ที่อธิบายความหมายได้ด้วยตัวมันเอง
* กลุ่ม macro ตามหน้าที่ (GPIO / Sensor / Network / App)

***

{% hint style="warning" %}

#### **ข้อควรระวัง (Pitfall)**

* การไม่ระบุ suffix (`U`, `f`) อาจทำให้เกิด type mismatch
* Macro ที่ชื่อไม่ชัดเจน จะทำให้โค้ดอ่านยากในระยะยาว
* การใช้ค่าคงที่ฝังในโค้ด (hard-coded) ทำให้แก้ไขยาก
  {% endhint %}

***

#### 📘 MISRA-C Note (สำหรับงานอุตสาหกรรม)

* MISRA-C อนุญาตให้ใช้ `#define` สำหรับ constant
* ควรหลีกเลี่ยง `#define` ที่ซับซ้อนหรือมี logic
* ค่าคงที่ที่เป็นกลุ่มเดียวกัน ควรถูกรวมไว้ใน header เดียว

***

**สรุปสั้น ๆ**

> ใช้ `#define` เพื่อแทนค่าคงที่เท่านั้น\
> ถ้าเริ่มมี logic → พิจารณาใช้ `static inline function` แทน

### <mark style="color:blue;">1.3 การใช้งานจริงของ Function-like Macros</mark>

Function-like macro เป็นเครื่องมือที่ถูกใช้บ่อยมากในงาน Embedded C\
โดยเฉพาะงานที่เกี่ยวข้องกับ **register control, sensor data processing และ performance-critical code**

อย่างไรก็ตาม macro ประเภทนี้ก็เป็นหนึ่งในแหล่งกำเนิด bug ที่พบบ่อยที่สุดเช่นกัน\
หากไม่เข้าใจข้อจำกัดและใช้งานอย่างระมัดระวัง

***

{% hint style="info" %}

#### **แนวคิด (Concept)**

Function-like macro คือ macro ที่มีลักษณะเหมือน function แต่ถูกแทนค่าตั้งแต่ขั้นตอน preprocessing\
จึง **ไม่มี type checking** และ **ไม่มีการป้องกัน side effect**

จุดเด่นคือ:

* เร็ว (ไม่มี function call overhead)
* ใช้กับ type ใดก็ได้ (type-generic)
* เหมาะกับ logic สั้น ๆ
  {% endhint %}

***

#### ตัวอย่าง Function-like Macros ที่ใช้บ่อย

```c
/* Min / Max macros - Generic for any type */
#define MIN(a, b)    ((a) < (b) ? (a) : (b))
#define MAX(a, b)    ((a) > (b) ? (a) : (b))

/* Clamp value to range - Limit sensor values */
#define CLAMP(val, min, max)  (MIN(MAX((val), (min)), (max)))

/* Bit manipulation macros - Register control */
#define BIT_SET(reg, bit)     ((reg) |=  (1U << (bit)))
#define BIT_CLEAR(reg, bit)   ((reg) &= ~(1U << (bit)))
#define BIT_TOGGLE(reg, bit)  ((reg) ^=  (1U << (bit)))
#define BIT_CHECK(reg, bit)   (((reg) >> (bit)) & 1U)

/* Array size macro - Prevent buffer overrun */
#define ARRAY_SIZE(arr)       (sizeof(arr) / sizeof((arr)[0]))

/* Unit conversion macros */
#define MS_TO_TICKS(ms)       ((ms) * configTICK_RATE_HZ / 1000U)
#define DEG_TO_RAD(deg)       ((deg) * 3.14159f / 180.0f)
#define CELSIUS_TO_F(c)       ((c) * 9.0f / 5.0f + 32.0f)
```

***

#### ตัวอย่างการใช้งานจริง (Real-world Usage)

**Sensor data validation**

```c
int16_t sensor_raw = read_sensor();
int16_t sensor_clamped = CLAMP(sensor_raw, -2000, 2000);
```

***

**Array iteration (ป้องกัน out-of-bounds)**

```c
int adc_readings[100];
size_t count = ARRAY_SIZE(adc_readings);

for (size_t i = 0; i < count; i++)
{
    process_reading(adc_readings[i]);
}
```

***

**GPIO register manipulation**

```c
uint32_t gpio_reg = 0;

BIT_SET(gpio_reg, 5);      /* Enable pin */
BIT_CLEAR(gpio_reg, 3);    /* Disable interrupt */

if (BIT_CHECK(gpio_reg, 5))
{
    printf("Pin 5 is HIGH\n");
}
```

***

**Temperature range limit**

```c
float temp = read_temperature();
float temp_limited = CLAMP(temp, -40.0f, 85.0f);
```

***

**FreeRTOS delay conversion**

```c
vTaskDelay(MS_TO_TICKS(100));   /* Delay 100 ms */
```

***

#### ตัวอย่างจากโค้ดจริงของ Infineon (IMU)

```c
#if IMU_SAMPLE_RANGE == BMI2_ACC_RANGE_2G
    #define IMU_ACC_DIVIDE  0x4000  /* 16384 */
#elif IMU_SAMPLE_RANGE == BMI2_ACC_RANGE_4G
    #define IMU_ACC_DIVIDE  0x2000  /* 8192 */
#elif IMU_SAMPLE_RANGE == BMI2_ACC_RANGE_8G
    #define IMU_ACC_DIVIDE  0x1000  /* 4096 */
#elif IMU_SAMPLE_RANGE == BMI2_ACC_RANGE_16G
    #define IMU_ACC_DIVIDE  0x0800  /* 2048 */
#endif
```

```c
#define IMU_INTR_MASK  (0x00000001UL << CYBSP_IMU_INT1_PORT_NUM)

#if defined(IMU_ACC) && defined(IMU_GYR)
    #define IMU_NUM_AXIS  (6U)   /* 3 accel + 3 gyro */
#else
    #define IMU_NUM_AXIS  (3U)   /* Only accel or gyro */
#endif
```

***

#### Best Practice

* ใส่วงเล็บรอบ **ทุก parameter และทุก expression**
* ใช้ macro กับ logic **สั้นและชัดเจนเท่านั้น**
* ใช้ชื่อ macro เป็น **ตัวพิมพ์ใหญ่ทั้งหมด**
* ใช้ macro สำหรับ register / bit manipulation จะเหมาะที่สุด

***

{% hint style="warning" %}

#### **ข้อควรระวัง (Pitfall)**

**❌ Side effect**

```c
#define MAX(a, b)  ((a) > (b) ? (a) : (b))

int x = 5;
int result = MAX(x++, 10);   /* x ถูกเพิ่มสองครั้ง */
```

**❌ Multi-statement macro ที่ไม่ใช้ `do { } while(0)`**

```c
#define LOG_ERROR(msg) printf("Error: %s\n", msg); error_count++
```

```c
if (failed)
    LOG_ERROR("Init failed");   /* error_count++ ทำงานเสมอ */
```

***

**✅ รูปแบบที่ถูกต้อง**

```c
#define LOG_ERROR(msg) do { \
    printf("Error: %s\n", msg); \
    error_count++; \
} while(0)
```

{% endhint %}

***

#### ⚖️ Macro vs Inline Function

| Aspect      | Macro       | Inline Function |
| ----------- | ----------- | --------------- |
| Type safety | ❌ No        | ✅ Yes           |
| Debugging   | ❌ Hard      | ✅ Easy          |
| Side effect | ❌ Dangerous | ✅ Safe          |
| Performance | ✅ Fast      | ✅ Fast          |

***

#### 📘 MISRA-C Note (สำหรับงานอุตสาหกรรม)

* MISRA-C แนะนำให้ **หลีกเลี่ยง function-like macro**
* อนุญาตเฉพาะ macro ที่:
  * ไม่มี side effect
  * ใช้กับ constant หรือ register
* Logic ที่ซับซ้อนควรใช้ `static inline function` แทน

```c
static inline int calculate_checksum(uint8_t *data, size_t len)
{
    int sum = 0;
    for (size_t i = 0; i < len; i++)
    {
        sum += data[i];
    }
    return (sum & 0xFF);
}
```

***

**สรุปสั้น ๆ**

> Function-like macro ทรงพลัง แต่ก็อันตราย\
> ถ้าเริ่มคิดนาน → อย่าใช้ macro

### <mark style="color:blue;">1.4 โครงสร้าง</mark> <mark style="color:blue;"></mark><mark style="color:blue;">`main()`</mark> <mark style="color:blue;"></mark><mark style="color:blue;">ที่แนะนำสำหรับ PSoC™ Edge E84</mark>

ฟังก์ชัน `main()` คือจุดเริ่มต้นของทุกโปรแกรม C\
ในงาน Embedded โดยเฉพาะบน **Infineon PSoC™ Edge E84**\
การจัดโครงสร้าง `main()` ให้ถูกต้องตั้งแต่ต้น จะช่วยให้ระบบ:

* ทำงานเสถียร
* ประหยัดพลังงาน
* Debug และขยายระบบได้ง่ายในอนาคต

***

{% hint style="info" %}

#### **แนวคิด (Concept)**

`main()` ในระบบ Embedded **ไม่ใช่โปรแกรมที่จบแล้ว exit**\
แต่เป็นจุดที่:

1. Initialize hardware และ system
2. Enable interrupt
3. เข้าสู่ main loop ที่ทำงานตลอดอายุของอุปกรณ์

ใน ModusToolbox โครงสร้าง `main()` ที่ดีควร:

* แยกขั้นตอน init อย่างชัดเจน
* ตรวจสอบ error ทุกครั้งที่ init
* รองรับ **Low power operation**
  {% endhint %}

***

#### โครงสร้าง `main()` พื้นฐานที่แนะนำ

```c
int main(void)
{
    cy_rslt_t result;

    /* 1. Initialize board and peripherals */
    result = cybsp_init();
    if (result != CY_RSLT_SUCCESS)
    {
        /* Critical error: stop execution */
        CY_ASSERT(0);
    }

    /* 2. Enable global interrupts */
    __enable_irq();

    /* 3. Initialize debug UART (optional) */
    cy_retarget_io_init(CYBSP_DEBUG_UART_TX,
                         CYBSP_DEBUG_UART_RX,
                         CY_RETARGET_IO_BAUDRATE);

    /* 4. Application-specific initialization */
    app_init();

    /* 5. Main loop */
    for (;;)
    {
        app_task();

        /* Enter deep sleep to save power */
        Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}
```

***

#### คำอธิบายแต่ละขั้นตอน

**1. `cybsp_init()`**

* Initialize clock, pins, peripherals ตาม BSP
* ต้อง **check return value เสมอ**
* ถ้าล้มเหลว → ระบบไม่ควรทำงานต่อ

**2. `__enable_irq()`**

* เปิด global interrupt
* ต้องเรียกหลังจาก init hardware เสร็จแล้ว
* ถ้าลืมเรียก → interrupt ทั้งระบบจะไม่ทำงาน

**3. `cy_retarget_io_init()` (optional)**

* ใช้ redirect `printf()` ไปที่ UART
* เหมาะสำหรับ debug / development
* ไม่จำเป็นใน production build เสมอไป

**4. Application Init / Task**

* ควรแยก logic ออกเป็น function
* หลีกเลี่ยงการเขียน code ยาว ๆ ใน `main()`

***

#### ตัวอย่างจริงจาก Infineon (hello-world project)

```c
/* From: mtb-example-psoc-edge-hello-world/proj_cm55/main.c */

int main(void)
{
    cy_rslt_t result;

    /* Initialize the device and board peripherals */
    result = cybsp_init();

    /* Board init failed. Stop program execution */
    if (CY_RSLT_SUCCESS != result)
    {
        __disable_irq();
        CY_ASSERT(0);
    }

    /* Enable global interrupts */
    __enable_irq();

    /* Put the CPU to Deep Sleep - saves power */
    for (;;)
    {
        Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}
```

***

#### Best Practice

* ตรวจสอบ return value ของ `cybsp_init()` ทุกครั้ง
* เรียก `__enable_irq()` หลัง init เสมอ
* แยก application logic ออกเป็น function (`app_init()`, `app_task()`)
* ใช้ **Deep Sleep** ใน main loop เมื่อไม่มีงาน

***

{% hint style="warning" %}

#### **ข้อควรระวัง (Pitfall)**

**❌ Loop เปล่า ๆ ที่ไม่ sleep**

```c
while (1)
{
    /* do nothing */
}
```

ผลลัพธ์:

* CPU ใช้งาน 100%
* เปลืองพลังงาน
* แบตเตอรี่หมดเร็วมาก

***

**❌ ลืม enable interrupt**

```c
cybsp_init();
/* forgot __enable_irq() */
```

ผลลัพธ์:

* Timer / UART / GPIO interrupt ไม่ทำงาน
* Debug ยากมาก
  {% endhint %}

***

#### 📘 MISRA-C Note (สำหรับงานอุตสาหกรรม)

* `main()` ต้องมี signature ชัดเจน (`int main(void)`)
* ไม่ควรมี code ที่ไม่ reachable
* Infinite loop เป็นสิ่งที่ **ยอมรับได้** ใน Embedded
* ควรหลีกเลี่ยง logic ซับซ้อนใน `main()`

***

#### สรุปสั้น ๆ

> `main()` ที่ดี\
> \= init ชัดเจน + check error + sleep เมื่อว่าง\
> คือหัวใจของ Embedded firmware ที่เสถียรและประหยัดพลังงาน

### <mark style="color:blue;">1.5 ANSI Escape Sequence สำหรับ Console Debug</mark>

ในระหว่างการพัฒนา Embedded firmware นักพัฒนามักใช้ `printf()` ผ่าน UART เพื่อ debug ค่า sensor, state machine หรือ system status

**ANSI Escape Sequence** คือชุดรหัสควบคุมพิเศษ\
ที่ทำให้ terminal สามารถ:

* ล้างหน้าจอ
* ย้ายตำแหน่ง cursor
* เปลี่ยนสีตัวอักษร
* จัด layout ข้อมูลแบบ real-time

ซึ่งมีประโยชน์มากในช่วง **development & debugging**

{% hint style="info" %}

#### **แนวคิด (Concept)**

ANSI Escape Sequence เป็น string ที่ขึ้นต้นด้วย **ESC character (ASCII 27)**\
ในภาษา C เขียนเป็น:

```c
\x1b
```

รูปแบบทั่วไป:

```
ESC [ <command>
```

ตัวอย่าง:

```c
\x1b[2J    // Clear screen
\x1b[H     // Move cursor to home
```

> Terminal ที่รองรับ: **Tera Term, PuTTY, Linux terminal**\
> Terminal ที่อาจไม่รองรับ: บาง Serial Monitor แบบง่าย
> {% endhint %}

```c
printf("\x1b[2J\x1b[;H");
//      ───┬─── ───┬───
//         │       │
//         │       └─ [;H = Move cursor to home (0,0)
//         └──────── [2J = Clear entire screen

// \x1b = ESC character (ASCII 27)
// ทำให้ terminal ล้างหน้าจอก่อนแสดงข้อความ
// ถ้าใช้ Tera Term หรือ PuTTY จะเห็นผล
// แต่ถ้าใช้ terminal ไม่รองรับ จะเห็นขยะ
```

***

#### ตัวอย่างพื้นฐานที่ใช้บ่อยที่สุด

**ล้างหน้าจอ + ย้าย cursor กลับจุดเริ่มต้น**

```c
printf("\x1b[2J\x1b[H");
```

อธิบาย:

```c
\x1b       // ESC character
[2J        // Clear entire screen
[H         // Move cursor to (0,0)
```

***

#### ตัวอย่างการใช้งานจริง (Real-world Usage)

**แสดงค่า sensor แบบ refresh หน้าจอ**

```c
while (1)
{
    printf("\x1b[2J\x1b[H");   /* Clear screen */

    printf("Temperature: %.2f C\n", temperature);
    printf("Humidity   : %.2f %%\n", humidity);
    printf("Pressure   : %.2f hPa\n", pressure);

    Cy_SysLib_Delay(1000);
}
```

ผลลัพธ์:

* หน้าจอไม่เลื่อนยาว
* ดูเหมือน dashboard แบบ real-time

***

**เปลี่ยนสีข้อความ (optional)**

```c
printf("\x1b[31mERROR\x1b[0m\n");   /* Red text */
printf("\x1b[32mOK\x1b[0m\n");      /* Green text */
```

สีที่ใช้บ่อย:

* `31` = Red
* `32` = Green
* `33` = Yellow
* `34` = Blue
* `0` = Reset

***

#### ทำไม ANSI Escape ถึงเหมาะกับ Embedded Debug

* ไม่ต้องใช้ GUI
* ใช้ resource น้อย
* เหมาะกับ board ที่ไม่มีจอ
* Debug ได้ผ่าน UART ธรรมดา

เหมาะมากกับ:

* Sensor bring-up
* Power consumption debug
* State machine monitoring

***

#### Best Practice

* ใช้ ANSI Escape **เฉพาะใน debug build**
* แยก debug output ด้วย macro

```c
#ifdef DEBUG_CONSOLE
#define CLEAR_SCREEN()  printf("\x1b[2J\x1b[H")
#else
#define CLEAR_SCREEN()
#endif
```

* ใช้ร่วมกับ `Cy_SysLib_Delay()` หรือ sleep เพื่อลด UART spam

***

{% hint style="warning" %}

#### **ข้อควรระวัง (Pitfall)**

**❌ Terminal ไม่รองรับ**

ถ้า terminal ไม่รองรับ ANSI:

* จะเห็นเป็นตัวอักษรแปลก ๆ เช่น `[2J[H`

**❌ ใช้ใน production firmware**

* เปลือง flash
* เปลือง UART bandwidth
* ไม่เหมาะกับระบบที่ต้อง deterministic timing
  {% endhint %}

***

#### ⚖️ ANSI Escape vs GUI Debug

| Aspect           | ANSI Escape | GUI Tool |
| ---------------- | ----------- | -------- |
| Resource         | ต่ำมาก      | สูง      |
| Setup            | ง่าย        | ซับซ้อน  |
| Flexibility      | ปานกลาง     | สูง      |
| Production ready | ❌           | ✅        |

***

{% hint style="success" %}

#### **MISRA-C Note (สำหรับงานอุตสาหกรรม)**

* ANSI Escape เป็น **string literal** → ไม่ผิด MISRA โดยตรง
* แต่:
  * ไม่ควรใช้ใน production code
  * ควรถูก guard ด้วย macro (`#ifdef DEBUG`)
* หลีกเลี่ยงการใช้ `printf()` ใน timing-critical path
  {% endhint %}

***

#### สรุปสั้น ๆ

> ANSI Escape = เครื่องมือ debug ที่ดีมาก\
> แต่ควรใช้ **เฉพาะตอนพัฒนา**\
> ไม่ใช่ solution ระยะยาวสำหรับ production system

### <mark style="color:blue;">1.6 Coding Style จากโค้ดตัวอย่างจริงของ Infineon (Hello-world & MQTT Multi-tasking)</mark>

หัวข้อนี้เป็นการ **สรุปแนวทางการเขียน C ที่ Infineon ใช้จริง**\
โดยอ้างอิงจากตัวอย่างทางการ เช่น:

* `mtb-example-psoc-edge-hello-world`
* ตัวอย่าง IoT / MQTT client ที่ใช้ **FreeRTOS multi-tasking**

เป้าหมายไม่ใช่แค่ “โค้ดรันได้”\
แต่คือ **เขียนให้ตรง mindset ของ Infineon และงานอุตสาหกรรม**

***

#### โครงสร้างโปรเจกต์ (Project Structure Mindset)

{% hint style="info" %}

#### **แนวคิด (Concept)**

จากตัวอย่างจริงของ Infineon จะเห็น pattern ชัดเจนว่า:

* `main.c` → ทำหน้าที่ **orchestration**
* logic งานจริง → แยกเป็น module
* hardware config → มาจาก BSP / Config Tool
* middleware → จัดการผ่าน Library Manager

โค้ด **ไม่กระจุกอยู่ไฟล์เดียว**
{% endhint %}

#### โครงสร้างที่พบได้บ่อย

```
proj_cm55/
 ├── main.c
 ├── app.c
 ├── app.h
 ├── FreeRTOSConfig.h
 ├── bsp/
 ├── middleware/
 └── generated/
```

***

#### Best Practice

* `main.c` ไม่ควรยาว
* Application logic ควรอยู่ใน `app_xxx.c`
* Hardware-specific code ไม่ควรปนกับ business logic
* ให้ Config Tool เป็นเจ้าของไฟล์ config (ไม่แก้มือ)

***

{% hint style="warning" %}

#### Pitfall

❌ เขียน logic ทั้งหมดใน `main.c`\
❌ แก้ไฟล์ที่ auto-generated → พังตอน regenerate\
❌ module หนึ่งทำหลายหน้าที่
{% endhint %}

***

#### Pattern ของ `main()` จาก Hello-world (Bare-metal Style)

{% hint style="info" %}

#### แนวคิด (Concept)

จาก hello-world ของ Infineon\
`main()` มีหน้าที่ชัดเจน 3 อย่าง:

1. Initialize system
2. Enable interrupt
3. เข้าสู่ loop ที่ประหยัดพลังงาน
   {% endhint %}

***

#### Pattern ที่พบจริง

```c
int main(void)
{
    cy_rslt_t result;

    result = cybsp_init();
    if (result != CY_RSLT_SUCCESS)
    {
        __disable_irq();
        CY_ASSERT(0);
    }

    __enable_irq();

    for (;;)
    {
        Cy_SysPm_CpuEnterDeepSleep(
            CY_SYSPM_WAIT_FOR_INTERRUPT);
    }
}
```

***

#### Best Practice

* check return value ทุกครั้ง
* error ร้ายแรง → หยุดระบบทันที
* idle loop ต้อง sleep เสมอ

***

#### MISRA-C Note

* Infinite loop ใน `main()` → ยอมรับได้
* หลีกเลี่ยง code ที่ unreachable
* `main()` ไม่ควรมี logic ซับซ้อน

***

#### สรุป 1.6

> ถ้าเขียนโค้ดให้ **โครงสร้างเหมือนตัวอย่างของ Infineon**\
> แปลว่าโค้ดคุณ “พร้อมต่อยอดเป็น production ได้จริง”

{% hint style="danger" %}

### Common Mistakes ที่ควรหลีกเลี่ยง

❌ เขียนทุกอย่างไว้ใน `main.c`\
❌ ไม่ check return value ของ init function\
❌ ใช้ macro แทน logic ที่ควรเป็น function\
❌ ใช้ printf เป็น logging หลักใน production\
❌ แก้ไฟล์ที่ Config Tool สร้างให้\
❌ ไม่คิดเรื่อง power consumption ตั้งแต่ต้น
{% endhint %}

***
