728x90
- 모터 드라이버 MD200T의 Source Code를 분석하며 공부한 내용
1) __attribute__
- 위 사진에 있는 __attribute__는 Unix/Linux의 GCC Compiler에 존재하는 메커니즘으로, compiler가 program에서 사용될 함수들을 더 주의해서 최적화하고 검사하도록 한다
- Function 선언시 compiler에게 특성을 주겠다는 것을 의마한다
- 뒤의 소괄호 안에 속성 인자를 작성하며 속성은 함수속성, 변수속성 그리고 타입속성의 종류로 구분된다
- 사용 이유
struct struct1{
char flags; // 1byte
short count; // 2byte
int msg; // 4byte
}
sizeif(struct1); // 8byte
- Structure 는 포함 요소들중 크기가 가장 큰 data type을 기준으로 그 크기의 배수만큼의 크기를 가진다
- 따라서 ST의 각 data type의 크기합은 7byte지만 크기가 가장 큰 int의 2배수인 8byte의 크기를 갖는다
- 이 때, 위 그림처럼 1byte의 padding(빈 공간)이 생기는 문제가 발생한다
struct struct2{
char flags; // 1byte
int msg; // 4byte
short count; // 2byte
}
sizeof(struct2); // 12byte
- 위처럼 member들의 배치 순서가 바뀌면 struct의 크기는 12byte가 된다
- CPU가 data type 저장시 효율을 위해 data type 크기의 배수에 해당하는 주소에 위치시키기 때문에 이같은 현상이 발생한다
- 1byte의 flags를 4byte를 할당하고 거기에 집어넣는다
- CPU가 memory address 지정시 4byte 단위가 내부적으로 가장 최적화되어있어 빠른 data access가 가능하므로 위와 같은 방식을 사용한다
- 위 같이 padding이 발생하는 것을 방지하고자 __attribute__ (packed) 메커니즘을 사용한다
struct struct{
char flags; // 1byte
int msg; // 4byte
short count; // 2byte
} __attribute__ ((packed)) struct_att
sizeof(struct_att); // 6byte
- 위와 같이 '__attribute__' 를 사용하여 compiler가 struct_att의 실제 크기만큼의 memory address를 할당하게 한다. (Struct의 member들이 memory address를 빈자리 없이 꽉 채우라는(packed) 의미)
- Padding은 사라지나 속도가 약간 늦어진다
- aligned(alignment) : Function에 대한 최소 정렬을 byte 단위로 나타낸다. 즉, struct의 memory에 몇 byte 단위로 끊어 위치시킬 것인지 나타낸다
- 따라서 위 코드에서는 구조체에 대한 memory 주소값이 1byte씩 나눠진다
- 정리
typedef struct {
int16_t rpm_id1; // 2bytes
int16_t current_id1; // 2bytes
MOTOR_STATE_t mtr_state_id1; // 1bytes
int32_t mtr_pos_id1; // 4bytes
int16_t rpm_id2; // 2bytes
int16_t current_id2; // 2bytes
MOTOR_STATE_t mtr_state_id2; // 1bytes
int32_t mtr_pos_id2; // 4bytes
} __attribute__((aligned(1),packed)) PID_PNT_MAIN_DATA_t;
sizeof(PID_PNT_MAIN_DATA_t); // 18bytes
- 구조체 PID_PNT_MAIN_DATA_t는 1bytes씩 나눠 총 32bytes 크기의 memory address를 할당받는다
- MOTOR_STATE_t는 다른 곳에서 정의된 1byte 크기의 union
2) <stdint.h>
- uint8_t는 <stdint.h> header에 정의된 data type으로, 모든 platform에서 동일한 bit 수를 사용하도록 설정하기 위해 사용한다 (C언어에서는 compiler의 종류나 OS의 차이에 따라 data type의 크기가 변경될 수 있다)
- Memory 관리가 중요한 Embedded 환경에서 자주 사용한다
- <stdint.h>의 source code
sites.uclouvain.be/SystInfo/usr/include/stdint.h.html
3) ros::Timer
- main.cpp source code의 일부
- Timer 함수는 ros::NodeHandle::createTimer()를 통해 생성할 수 있다 (위 코드에선 app_tick_timer)가 Nodehandle 역할)
- Duration은 timer 호출 간격. 위 코드에선 0.5초의 간격을 둠
- AppTickTimerCallback은 timer의 callback Function
- Callback Function : 다른 function의 실행이 끝난 후 실행되는(callback 되는) function으로, 다른 function의 parameter로 사용되는 실행 가능한 function이다
ros::Timer app_tick_timer = nh.createTimer(ros::Duration(0.500), AppTickTimerCallback1, true);
ros::Timer app_tick_timer = nh.createTimer(ros::Duration(0.500), AppTickTimerCallback2, false);
- 위처럼 callback function 뒤에 true, false를 지정할 수 있다
- true의 경우 one shot timer가 되어 한 번만 호출된다. 따라서 AppTickTimerCallback1 function은 0.5s동안 한 번만 호출된다
- false일 경우 stop될 때까지 호출된다 (생략가능)
참고 자료 :
https://dobby-the-house-elf.tistory.com/358
https://pastime0.tistory.com/entry/attribute-packed-%EA%B5%AC%EC%A1%B0%EC%B2%B4-%EC%A0%95%EB%A0%AC
https://indra17.tistory.com/entry/GNU-C-attribute
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=msyang59&logNo=220885276415
https://educoder.tistory.com/entry/cc-int8t-uint8t-int16t-uint16t
https://nevertrustbrutus.tistory.com/58
https://ko.wikipedia.org/wiki/%EC%BD%9C%EB%B0%B1
https://m.blog.naver.com/nimtedd41/221671309534
'Project > RIS' 카테고리의 다른 글
[RIS] CURT 작성 초안 (0) | 2023.01.10 |
---|---|
[RIS] 1/9 (initial pose/goal, odometry publisher, ekf) (0) | 2023.01.09 |
[RIS] 모터 드라이버(MD 200T) 관련 문제점 (12/15 ~ 1/10. 해결) (7) | 2023.01.03 |
[RIS] 1/2 (USB 장치의 Symbolic Link 생성법) (0) | 2023.01.02 |
[RIS] 12/26 (MDAS) (0) | 2022.12.26 |