'[B-01] Quad-rotor' 카테고리의 다른 글
Headholding (0) | 2009.12.22 |
---|---|
Tilt-camera (0) | 2009.12.22 |
Indoor flying (0) | 2009.12.22 |
GPS용 지도 만들기 입문 (0) | 2009.12.04 |
XBee-Pro의 RSSI 측정 (0) | 2009.12.03 |
Headholding (0) | 2009.12.22 |
---|---|
Tilt-camera (0) | 2009.12.22 |
Indoor flying (0) | 2009.12.22 |
GPS용 지도 만들기 입문 (0) | 2009.12.04 |
XBee-Pro의 RSSI 측정 (0) | 2009.12.03 |
Tilt-camera (0) | 2009.12.22 |
---|---|
Outdoor flying (0) | 2009.12.22 |
GPS용 지도 만들기 입문 (0) | 2009.12.04 |
XBee-Pro의 RSSI 측정 (0) | 2009.12.03 |
256-MBIT SYNCHRONOUS DRAM - IS42S16160B (0) | 2009.11.12 |
今臣戰船尙有十二 (0) | 2009.12.28 |
---|---|
__attribute__((packed)) (0) | 2009.12.28 |
[UTIL] EASEUS Partition (0) | 2009.12.21 |
SAMPLE 전자에서 판매되는 각종 센서 모음 사이트 (0) | 2009.12.08 |
Kernel을 Porting 한다는 것 (0) | 2009.12.04 |
__attribute__((packed)) (0) | 2009.12.28 |
---|---|
[UTIL] FileZilla (0) | 2009.12.21 |
SAMPLE 전자에서 판매되는 각종 센서 모음 사이트 (0) | 2009.12.08 |
Kernel을 Porting 한다는 것 (0) | 2009.12.04 |
DPC(Deferred Procedure Call) (0) | 2009.12.04 |
Peter.Baumann@dir.de
schun@crypto.pe.kr
텔넷 접속 프로그램 (0) | 2009.12.27 |
---|---|
부팅디스트 만들기 (0) | 2009.12.26 |
임베디드 시스템 엔지니어를 위한 리눅스 커널 분석 (0) | 2009.12.04 |
Basic Graphics Programming With The Xlib Library (0) | 2009.11.26 |
X 윈도우 프로그래밍 기초과정 (0) | 2009.11.26 |
[STM32F10x_StdPeriph_Driver] void RCC_Configuration(void) 함수 (0) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SetSysClockTo72(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
[STM32F10x_StdPeriph_Driver] void RCC_APB2PeriphClockCmd ( uint32_t RCC_APB2Periph, FunctionalState NewState ) 함수 (1) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SetSysClockTo72(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
[STM32F10x_StdPeriph_Driver] void RCC_APB2PeriphClockCmd ( uint32_t RCC_APB2Periph, FunctionalState NewState ) 함수 (1) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void RCC_Configuration(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
[STM32F10x_StdPeriph_Driver] void RCC_Configuration(void) 함수 (0) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SetSysClockTo72(void) 함수 (0) | 2009.12.10 |
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
STM32F10xxx Cortex-M3 programming manual (0) | 2009.12.06 |
SystemInit() 함수에 대해서 분석해 보고자 한다.
우선 ST에서 제공하는 라이브러리에 포함된 도움말 파일에는 다음과 같이 정의하고 있다.
[STM32F10x_StdPeriph_Driver] void SetSysClockTo72(void) 함수 (0) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
STM32F10xxx Cortex-M3 programming manual (0) | 2009.12.06 |
An Introduction to the ARM Cortex-M3 Processor (0) | 2009.12.04 |
STM 라이브러리에서 제공하는 Clock 초기화 관련 함수들을 이용해서 72MHz의 시스템 클럭을 설정하는 방법에 대하여 알아보았다.
먼저 STMicroelectronics 홈페이지에 가서 라이브러리를 다운 받는다.
Link : http://www.st.com/mcu/devicedocs-STM32F103RB-110.html
#if !defined (STM32F10X_LD) && !defined (STM32F10X_MD) && !defined (STM32F10X_HD) && !defined (STM32F10X_CL)
/* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */
#define STM32F10X_MD /*!< STM32F10X_MD: STM32 Medium density devices */
/* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */
/* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */
#endif
STM32F103RB는 medium density devices이므로 STM32F10X_MD를 활성화 해주어야 한다.
세번째,
stm32f10x.h 파일에 아래와 같이 추가한다.
/**
* @brief In the following line adjust the value of External High Speed oscillator (HSE)
used in your application
Tip: To avoid modifying this file each time you need to use different HSE, you
can define the HSE value in your toolchain compiler preprocessor.
*/
#define EXT_CLOCK_SOURCE_12M
#if !defined HSE_Value
#ifdef STM32F10X_CL
#define HSE_Value ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#else
#ifdef EXT_CLOCK_SOURCE_12M
#define HSE_Value ((uint32_t)12000000) /*!< Value of the External oscillator in Hz */
#else
#define HSE_Value ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif
#endif /* STM32F10X_CL */
#endif /* HSE_Value */
현재 사용중인 보드는 외부에 12MHz의 crystal을 사용하므로 HSE_Value를 12000000으로 설정하고 나중에 사용하게 된다.
네번째,
system_stm32f10x.c 파일을 아래와 같이 수정한다.
/* #define SYSCLK_FREQ_HSE HSE_Value */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
SYSCLK_FREQ_72MHz를 72000000으로 설정해 놓았으므로,
SetSysClockTo72()함수가 호출된다.
다섯번째,
system_stm32f10x.c 파일의 SetSysClockTo72() 함수를 아래와 같이 수정한다.
#elif defined SYSCLK_FREQ_72MHz
/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK/2 */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
/* if EXT_CLOCK_SOURCE_12M, PLL configuration: PLLCLK = HSE * 6 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
#ifdef EXT_CLOCK_SOURCE_12M
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
#else
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
/* Go to infinite loop */
while (1)
{
}
}
}
#endif
외부에 12MHz의 crystal을 사용하므로 PLLMUL6으로 하여 12000000MHz * 6 = 72000000MHz를 사용할 수 있게 된다.
모든 설정이 끝나면 다시 빌드하여 프로그램을 실행해 본다.
[STM32F10x_StdPeriph_Driver] void SetSysClock(void) 함수 (0) | 2009.12.10 |
---|---|
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
STM32F10xxx Cortex-M3 programming manual (0) | 2009.12.06 |
An Introduction to the ARM Cortex-M3 Processor (0) | 2009.12.04 |
The STM32 Primer Commnity (0) | 2009.12.03 |
kmz51_example1을 기준으로 avr 소스 수정
C#에서 가끔 에러 나는거 잡기 : 도대체 이유를 모르것음
구동 방법
뭐 AVR에 프로그램 넣고, C# 프로그램 구동하면 된다.
[Chapter01] 실습환경 설정 및 준비 - 02.커널소스 준비 (0) | 2009.12.28 |
---|---|
[Chapter01] 실습환경 설정 및 준비 - 01.시스템과 리눅스 운영체제의 준비 (0) | 2009.12.28 |
CMPS03 지자기 센서를 이용한 방위각 측정 3/4 : AVR & Future Works (0) | 2009.12.08 |
CMPS03 지자기 센서를 이용한 방위각 측정 2/4 : C# Application (0) | 2009.12.08 |
CMPS03 지자기 센서를 이용한 방위각 측정 1/4 : CMPS03 Introduction (0) | 2009.12.08 |
* AVR Program
AVR측 프로그램입니다. I2C가 완성되지 않았기 때문에 별거 없어요.
스위치 입력 받을때마다 시리얼 포트로 @090!, @180!, @270!, @360!을 전송하게 되어있습니다.
I2C를 짠다음에 또 올려보도록 하죠.
* Future Works
1. 프로그램을 안전하게 종료시키기
프로그램을 닫을때 시리얼 포트 및 모든 자원을 해제 해야 하는데, 대충 닫았습니다.
종종 다시 시리얼 포트가 열릴때 문제가 생깁니다. ^^
급하게 만들다 보니 이런실수가.. 크흑
2. 시리얼 클래스를 외부로 뽑기
여기저기서 시리얼 클래스를 쓰는데, 매번 코드 복사하는것도 번거로와서, 뭔가 해결책을 찾아야 하는데 말이죠 ^^
걍 클래스로만 만들어도 되나요? 뭐 DLL 이런걸로 만들어야 되나요?
3. C#에서 파싱하기
AVR에서 쑥떡같이 보내도 C#에서 찰떡같이 알아듣기
현재는 이렇게 보냅니다. @XYZ! XYZ는 각각 100의 자릿수, 10의 자릿수, 1의 자리수..
고로, 45를 보내려고 해도, @45! 하믄 안되고, @045!와 같이 보내야 합니다.
왜냐하면, C#에서
if(str.StartsWidt(@)||str.EndsWidth(!)) { ...
str.SubString(1,3);
이렇게 읽기 때문이죠.
4. AVR에서 문자열 입력 받기
도대체 하이퍼 터미널에서 "200" 이라고 문자열을 입력하면 AVR에서 어떻게 200이라고 알수 있을까요?
문제는 입력되는 숫자가 가변적임, 즉 "3"이 올수도 있고, "45910"이 올수도 있음. 물론 끝에 엔터는 들어감
문자열 보내는 것도 짜증나고, 받는 것도 짜증나요.
긍까 하이퍼 터미널에서 문자열로 30이 오면 AVR에서 숫자로 30을 받고 싶다는 거죠
5. 지자기 센서 읽기
데이터 쉬트 보고 읽으면 되지 않을까요? ^^
[Chapter01] 실습환경 설정 및 준비 - 01.시스템과 리눅스 운영체제의 준비 (0) | 2009.12.28 |
---|---|
CMPS03 지자기 센서를 이용한 방위각 측정 4/4 : 완료 (0) | 2009.12.08 |
CMPS03 지자기 센서를 이용한 방위각 측정 2/4 : C# Application (0) | 2009.12.08 |
CMPS03 지자기 센서를 이용한 방위각 측정 1/4 : CMPS03 Introduction (0) | 2009.12.08 |
SPI 개요 (0) | 2009.11.12 |
전체 구조는 위와 같습니다.
지자기 센서의 I2C 출력값을 ATmega32에서 받아서, PC로 시리얼 통식 방식으로 쏩니다.
이 값을 받아서 PC 어플리케이션이 처리합니다.
PC 어플리케이션은 C#, VB, C++ 원하시는 툴로 짜면 됩니다. 당근이는 C#으로 짰음.
아래 예제가 있음돠.
이거 예제 짤때 쪼까 고생했는데, 고생한 목록은 다음과 같습니다.
1. 시계 모양으로 땡구라미를 그리는게 좀 힘들었습니다. 위의 조그만 동그라미들은 이미지가 아니라 좌표 계산하여 그린겁니다.
고로, 프레임을 확대 축소해도 깨지지 않아요. 동구라미 좌표 그릴때 등방성 좌표계를 이용한다는데.. 거 뭔말인지..
2. 트랙바로 움직이게 했는데, 트랙바보다는 vertical Slider가 더 이쁜거 같더군요. (뭐야 이건 어려운게 아니잖아!)
3. 설명드리기가 곤란한데, 가장 복잡했던점이..
당근이가 만든 Compass 클래스에서 OnPaint 메소드를 호출했더니, 자꾸 에러가 나더군요.
UsrControl을 상속받아야 했구요.
처음에는 패널의 Graphics 객체를 Compass에서 받아와서 처리했는데, 보통 그렇게 하지 않더군요.
걍 Compass의 Graphics에서 createGraphics를 한 이후에 Compass를 생성할때 Graphics를 넘겨주는 방식..
조금 버벅 댔음
4. 더블 버퍼링.. 그래도 조금 어려울줄 알았는데, 한줄이면 되더군요. ㅜㅠ
아래는 소스 짜는 중 이것 저것 캡쳐해본검돠.
초기 버젼 : 아직 시리얼을 못 붙였음
개선중 : 패널 제거작업 (크하하.. 패널 뒤에 있어서 안그려지는 알고 거의 30분 삽질 ㅜㅠ)
최종 버젼
예제 소스 설명
1. 초기 프로토 타입 : 클래스 설계 개판
2. 어쨌든 움직이게 했다.
3. 더블 버퍼링
4. 시리얼 입력 받음 : 옆의 슬라이더와 동시에 받음
현재 작업 내역
컴 마스터로 당근보드의 스위치를 누르면 이 값이 PC의 C# 프로그램으로 갑니다.
그라무네, 나침반이 90, 180, 270, 360도 이렇게 움직입니다. 버튼이 뭐 4개밖에 없어서 걍 편하게 짰음
서서히 정회전 역회전 할수도 있지만, 나중에 하기로 하고 오늘은 여기까지 !
CMPS03 지자기 센서를 이용한 방위각 측정 4/4 : 완료 (0) | 2009.12.08 |
---|---|
CMPS03 지자기 센서를 이용한 방위각 측정 3/4 : AVR & Future Works (0) | 2009.12.08 |
CMPS03 지자기 센서를 이용한 방위각 측정 1/4 : CMPS03 Introduction (0) | 2009.12.08 |
SPI 개요 (0) | 2009.11.12 |
Dual bidirectional bus buffer (P82B96) (0) | 2009.11.07 |
CMPS03 지자기 센서를 이용한 방위각 측정을 해보려고 합니다.
2008.06.28 현재 센서값을 읽지는 못했습니다. 좀 시간내서 더 짜봐야 할듯요. I2C 하기 싫어서.. ㅜㅠ
환경은 알아서 구성해 주세요.
당근이는 XP, Visual Studio 2005 C#, AvrStudio ?.?.14, 당근보드, 뭐 이렇게 사용합니다.
일단 CMPS03 라는 놈이 모냐? 쉽게 설명하면 "Compass(나침반)"이라고 생각하면 됩니다.
http://www.touchsensor.co.kr/robotelec/se-cmps.htm
조기서 판매하고 있고요. 각종 자료나 소스도 제공해 줍니다. 물론 BASCOM이나 VB를 안쓰기 때문에, 당근이는 그닥 필요가.. ㅜㅠ
데이터 포맷은 아직 데이터 쉬트를 못봐서 모르겠지만, 북쪽이면 0, 남쪽이면 180 뭐 이렇게 나오지 않을까 싶네요. 사진 함 구경해 보죠.
요로코롬 생긴놈입니다. PIC를 제거하면 엄지 손톱만 해지지도 않을까 생각해 봅니다.
누가 PCB 비용이라도 주믄 함 만들어 보겠다. ㅋㅋㅋ
흠. 지자기 센서가 I2C를 지원안하니까, PIC는 꼭 있어야 하나? 어쩌나? 흠 모르것다.
핀 디스크립션은 위와 같구요.
NC는 도대체 왜 뽑아놓은건지..
얘는 I2C로 출력하므로, I2C 포맷을 알아야 합니다.
제어에 대한 자세한 내용은 데이터쉬트를 참조.. ^^
다음에는 프로그램 함 보도록 하죠.
Visual Studio가 없으신 분들은 첨부파일을 다운로드 하여 실행해 보면 됩니다.
옆의 슬라이더를 움직이면, 바늘이 움직입니다.
즉, 지자기 센서의 값을 읽어서 슬라이더를 움직이는 것과 동일한 이벤트를 발생시키겠다는 거죵. 대략 이해가 가시겠죠?
CMPS03 지자기 센서를 이용한 방위각 측정 3/4 : AVR & Future Works (0) | 2009.12.08 |
---|---|
CMPS03 지자기 센서를 이용한 방위각 측정 2/4 : C# Application (0) | 2009.12.08 |
SPI 개요 (0) | 2009.11.12 |
Dual bidirectional bus buffer (P82B96) (0) | 2009.11.07 |
I2C-bus specification and user manual (0) | 2009.10.24 |
[UTIL] FileZilla (0) | 2009.12.21 |
---|---|
[UTIL] EASEUS Partition (0) | 2009.12.21 |
Kernel을 Porting 한다는 것 (0) | 2009.12.04 |
DPC(Deferred Procedure Call) (0) | 2009.12.04 |
Call Back Function (0) | 2009.12.04 |
[STM32F10x_StdPeriph_Driver] void SystemInit(void) 함수 (0) | 2009.12.10 |
---|---|
STM32F103RB 72MHz 시스템 클럭 설정하는 방법 (0) | 2009.12.09 |
An Introduction to the ARM Cortex-M3 Processor (0) | 2009.12.04 |
The STM32 Primer Commnity (0) | 2009.12.03 |
STM32 USART (interrupt mode) Example (0) | 2009.12.03 |
[UTIL] EASEUS Partition (0) | 2009.12.21 |
---|---|
SAMPLE 전자에서 판매되는 각종 센서 모음 사이트 (0) | 2009.12.08 |
DPC(Deferred Procedure Call) (0) | 2009.12.04 |
Call Back Function (0) | 2009.12.04 |
친절한 임베디드 시스템 개발자 되기 강좌 (0) | 2009.12.03 |
SAMPLE 전자에서 판매되는 각종 센서 모음 사이트 (0) | 2009.12.08 |
---|---|
Kernel을 Porting 한다는 것 (0) | 2009.12.04 |
Call Back Function (0) | 2009.12.04 |
친절한 임베디드 시스템 개발자 되기 강좌 (0) | 2009.12.03 |
MOSFET (0) | 2009.12.02 |
콜백의 기본 개념
일반적인 의미에서 콜백이란 호출자(Caller)가 피호출자(Callee)를 호출하는 것이 아니라 피호출자가 호출자를 호출하는 것을 말한다(<그림 1> 참조). 콜백이 많이 사용되는 전형적인 예는 WIN32 API이다. 대개의 경우 응용 프로그램이 WIN32 API를 호출하는 거서이 일반적이지만 때때로 윈도우 시스템이 응용 프로그램을 호출해야 할 때가 있다. 이때 응용 프로그램은 콜백 함수를 윈도우 시스템에게 알려주고 어떤 조건이 만족되면 윈도우 시스템이 콜백 함수를 호출해 준다. WIN32 API의 EnumWindow, SetTimer 함수 등이 콜백을 사용하며 윈도우 프로시저(window procedure) 역시 콜백 개념을 사용한다.
<그림 2>는 전형적인 콜백 메커니즘을 보여주고 있다. 콜백 메커니즘의 순서로써
(1) 호출자는 콜백 메서드의 참조(함수 포인터)를 매개 변수로 하여 피호출 메서드를 호출한다.
(2) 피호출 메서드는 매개 변수로 전달된 콜백 메서드에 대한 참조를 필드와 같은 곳에 기록해 둔다.
(3) 이제 콜백을 수행할 어떤 조건(이 조건은 다양할 수 있다)이 만족되면 ...
(4) 기록해 둔 콜백 메서드 참조를 이용하여 콜백 메서드를 호출하게 된다.
물론 모든 콜백이 <그림 2>와 같은 순서를 따르는 것은 아니지만 많은 경우 이와 같은 시나리오를 따르는 것이 일반적이다. 콜백을 수행할 조건을 만족하는지 지속적으로 검사하는 과정이 필요하기 때문에 별도의 스레드를 이용하는 경우가 대부분이며, 콜백 메서드를 호출하는 스레드 역시 조건을 검사하는 스레드이기 때문에
콜백 메서드는 서로 다른 스레드에서 호출되는 것이 일반적이다. 이렇게 다중 스레드를 사용하기 때문에 비동기(asynchronous) 작업을 수행할 때 비동기 작업이 완료되었음을 알리기 위한 방법으로 콜백 메커니즘이 많이 사용되곤 한다.
참조: http://imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=29268
OS에 의해 직접 불려지는 함수를 CALLBACK 함수라고 한다. 예를 들면 WndProc 콜백 함수는 EVENT 발생시 OS에 의해 직접 호출되며, 이때 Message 종류와 내용을 Parameter로 전달 받는다.
Callback routines are defined by the user program, instructing the graphic system to call a specific function when a specific event occurs. Normally they are used to automatically redraw a window when its content has changed.
CALLBACK 함수는 메시지를 처리한다. 윈도우즈 자체가 메시지 기반으로 작동하기 때문에 우리가 아무것도 안하면 혼자 놀고 있다가 버튼이라도 하나 누르면 그 버튼 ID에 따른 처리를 해준다. 이런 처리를 해주는 부분이 CALLBACK 함수이다.
CALLBACK으로 선언된 함수는 윈도우 운영체제에서 특정한 사건이 발생될 때 운영체제로부터 호출돼는 함수이다. 예로 Timer가 있다. Timer는 사용자가 프로그램에서 얼마 간격으로 SetTimer를 설정하면 운영체제가 그 시간이 돼면 OnTimer 함수를 호출한다.
CALLBACK 함수는 불려지는 쪽에서 부르는 쪽의 데이터를 참조하거나 핸들링 하는 함수이다. 윈도우는 data segment와 code segment가 분리되어 있다. code는 공유를 하나 data는 공유 하지 않는다. 공유하게 되면 심각한 문제가 발생할 것이다. 그래서 나온 것이 CALLBACK 함수이다.
예를 들어 설명하면,
'A'라는 DLL이 'B'라는 DLL을 불러 쓰고 'A'라는 DLL에는 동적으로 메모리를 할당 받을 변수와 메모리를 할당하고 해제하는 함수가 있다고 가정하고 'B'라는 DLL에서 이 변수에 동적으로 메모리를 할당하고 처리하려 한다고 할 때 'B'에서 'A'의 변수를 인자로 받아 메모리를 할당하고 처리하는 것은 무의미 하거나 위험하다. 앞에서 말했듯이 'A'와 'B'는 서로 독립된 DATA SEGMENT를 갖기 때문이다. 그렇다면 B는 A의 메모리 할당 함수를 이용해서 A의 변수에 메모리를 할당하고 해제 해야한다. 여기에서 A에서 B로 넘겨주는 메모리 할당 함수를 CALLBACK 함수라고한다. 다시말해서 불려지는 쪽에서 부르는 쪽의 DATA를 참조하기 위한 교량 역할을 하는 것이 CALLBACK 함수인 것이다. WNDPROC가 CALLBACK 함수인 이유도 여기에 있다. 애플리케이션에 의해 불려지는 운영체제에서 디폴트 윈도우 프로시져의 위치에 부르는 함수이기 때문이다.
Kernel을 Porting 한다는 것 (0) | 2009.12.04 |
---|---|
DPC(Deferred Procedure Call) (0) | 2009.12.04 |
친절한 임베디드 시스템 개발자 되기 강좌 (0) | 2009.12.03 |
MOSFET (0) | 2009.12.02 |
네이버 블로그/카페에서 우클릭 및 내용 선택하기 (0) | 2009.12.01 |