null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
⌂
Embedded C 학습 로드맵
Structure
what-is-embedded-system
•
임베디드 SW vs 일반 SW
•
CPU 아키텍처 기초
•
메모리 레이아웃
development-environment
•
툴체인 개요
•
프로젝트 & 라이브러리 구조
•
플래싱 & 디버깅
c-language-for-embedded
•
데이터 타입과 이식성
•
비트 연산
•
volatile과 최적화
gpio
•
GPIO 개념
•
출력 제어
•
입력 읽기 & 디바운스
basic-uart
•
UART 프레이밍 & 보레이트
•
송수신 구현
•
UART 디버그 출력
Flow Structure
플래싱 & 디버깅
7 / 15
비트 연산
☆ Star
↗ Full
데이터 타입과 이식성
#stdint
#uint8
#fixed-width
#sizeof
#portability
@devpc
|
2026-04-02 05:47:09
|
GET /api/v1/flows/10/nodes/200?fv=2&nv=1
Context:
Flow v2
→
Node v1
0
Views
3
Calls
# 데이터 타입과 이식성 ## 문제: int의 크기는 보장되지 않는다 C 표준에서 `int`의 크기는 플랫폼에 따라 다릅니다. ``` 플랫폼 int 크기 ───────────────────────── 16비트 MCU 2 bytes 32비트 MCU 4 bytes (일반적) 64비트 PC 4 bytes (일반적이지만 보장 안 됨) ``` 임베디드에서 레지스터 비트를 다루거나 통신 프로토콜을 구현할 때, **타입의 크기가 정확히 보장**되어야 합니다. 그래서 임베디드 C에서는 `<stdint.h>`의 고정폭 타입을 사용합니다. --- ## stdint.h — 고정폭 타입 ```c #include <stdint.h> /* 부호 있는 (signed) 정수 */ int8_t a; /* 8비트, -128 ~ 127 */ int16_t b; /* 16비트, -32768 ~ 32767 */ int32_t c; /* 32비트, -2147483648 ~ 2147483647 */ int64_t d; /* 64비트 */ /* 부호 없는 (unsigned) 정수 */ uint8_t e; /* 8비트, 0 ~ 255 */ uint16_t f; /* 16비트, 0 ~ 65535 */ uint32_t g; /* 32비트, 0 ~ 4294967295*/ uint64_t h; /* 64비트 */ ``` **규칙**: 임베디드에서는 `int`, `long` 대신 항상 `uint32_t`, `uint8_t` 등을 쓰세요. 크기가 명확하고, 코드 리뷰 시 의도가 분명해집니다. --- ## sizeof 연산자 `sizeof`는 컴파일 타임에 타입의 바이트 크기를 반환합니다. ```c sizeof(uint8_t) /* → 1 */ sizeof(uint16_t) /* → 2 */ sizeof(uint32_t) /* → 4 */ sizeof(uint64_t) /* → 8 */ /* 구조체 크기 — 패딩 때문에 합산과 다를 수 있음! */ typedef struct { uint8_t a; /* 1 byte */ uint32_t b; /* 4 bytes → 앞에 3 bytes 패딩 삽입 가능 */ } MyStruct; sizeof(MyStruct) /* → 8 (패딩 포함) */ ``` ``` [ 구조체 메모리 레이아웃 (패딩 예시) ] offset 0: [ a ] [pad] [pad] [pad] offset 4: [ b (4 bytes) ] 총 8 bytes ``` 레지스터 맵이나 통신 패킷 구조체를 정의할 때 패딩이 끼어들면 오동작합니다. 이 경우 `__attribute__((packed))` 또는 `#pragma pack`으로 패딩을 제거합니다. --- ## 플랫폼 의존성 주의 사항 ```c /* ❌ 위험: 크기 미보장 */ unsigned char x; /* 보통 8비트지만 표준 보장 없음 */ unsigned int y; /* 플랫폼마다 다름 */ unsigned long z; /* 32비트? 64비트? 플랫폼마다 다름 */ /* ✅ 안전: 크기 보장 */ uint8_t x; uint32_t y; uint32_t z; ``` --- ## TC37x: iLLD의 타입 시스템 iLLD는 `stdint.h`를 기반으로 하되, `Ifx_` 접두어를 붙인 별칭 타입을 추가로 제공합니다. ```c /* iLLD 타입 (IfxStdIf_DPipe.h 등에 정의됨) */ typedef uint8_t Ifx_uint8; typedef uint16_t Ifx_uint16; typedef uint32_t Ifx_uint32; typedef float Ifx_float32; typedef double Ifx_float64; ``` iLLD 내부에서는 `Ifx_uint32`를 자주 씁니다. 애플리케이션 코드에서는 `uint32_t`를 직접 써도 무방합니다. 두 타입은 동일한 크기입니다. ### 비트필드 union 타입 레지스터 값을 다룰 때 iLLD는 **union + 비트필드** 구조를 사용합니다. ```c /* SCU_OSCCON 레지스터 예시 (iLLD) */ typedef union { uint32_t U; /* 전체 32비트를 한 번에 읽기/쓰기 */ struct { uint32_t PLLLV : 1; /* 비트 0 */ uint32_t OSCRES : 1; /* 비트 1 */ uint32_t : 2; /* 예약 (비트 2~3) */ uint32_t GAINSEL: 2; /* 비트 4~5 */ /* ... */ } B; /* 비트 단위로 접근 */ } Ifx_SCU_OSCCON; ``` ```c /* 사용 예 */ Ifx_SCU_OSCCON osccon; osccon.U = 0; /* 전체 초기화 */ osccon.B.GAINSEL = 3; /* GAINSEL 비트만 설정 */ MODULE_SCU.OSCCON.U = osccon.U; ``` --- ## 다른 MCU와의 차이점 > ⚠️ 다른 환경에서 넘어온다면 이런 점이 다를 수 있습니다. - **stdint.h 사용**: STM32 CMSIS도 동일하게 `uint32_t` 등을 사용. 이 부분은 거의 동일. - **비트필드 union**: STM32 CMSIS도 유사한 구조 사용. ARM과 TriCore 모두 32비트라 레지스터 폭은 동일. - **엔디안(Endian)**: TriCore는 Little-Endian. ARM Cortex-M도 기본 Little-Endian. 통신 프로토콜에서 Big-Endian이 필요하면 변환 필요.
플래싱 & 디버깅
비트 연산
// COMMENTS
Newest First
ON THIS PAGE
No content selected.