Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

임베디드 소프트웨어/Zephyr

[nRF52840 + Zephyr] #10. Time management

방피터 2023. 6. 3. 10:38

제퍼도 다른 os와 마찬가지로 여러가지 시간관련 기능을 제공하고 있어.
대표적인게 os timer야.
임베디드 프로젝트를 하다보면 타이머를 자주 사용하게 되는데.

타이머를 하드웨어로 돌리려면 하드웨어 사용 설정하고, 주기 설정하고, 인터럽트 작성해주고, 혹시나 동작이 길면 global flag 설정해주고 인터럽트 외주에서 나머지 동작을 처리해야 하지. ㅋㅋㅋ
🤪😜😝😅😢😣😖😞😤😳
데이터시트도 읽어야 하는 건 덤이고 말이야 ㅋ

아주 그냥 대환장 파티.
그에 비해 os timer는 사용 설정하고 쓰면 끝이야.
매우 간편!

👇👇

struct k_timer my_timer;
extern void my_expiry_function(struct k_timer *timer_id);

k_timer_init(&my_timer, my_expiry_function, NULL);

아니면 아래처럼 관련 매크로를 사용해서 컴파일타임에서 선언할 수도 있지.

K_TIMER_DEFINE(my_timer, my_expiry_function, NULL);
//K_TIMER_DEFINE(타이머 이름, 타이머 만료 콜백, 타이머 중지 콜백);

그리고 사용은

   👇👇

k_timer_start(&my_timer, K_SECONDS(1), K_SECONDS(1));//1초 후 만료되는 타이머를 1초 주기로 반복
//or
k_timer_start(&my_timer, K_MSEC(100), K_NO_WAIT);// 100ms(0.1초) 후 타이머 만료.
//or
k_timer_start(&my_timer, K_MSEC(100), K_SECONDS(1));//100ms(0.1초)후 만료되는 타이머를 1초 주기로 반복

정해진 시간이 끝나면 등록해 두었던 my_expiry_function이 수행되지.

정말 간단하게 타이머를 사용할 수가 있어.

 

역시나 억지로 예제를 만들어보자구

#include <zephyr/kernel.h>

//declaration
void my_expiry_function(struct k_timer *timer_id);

K_TIMER_DEFINE(my_timer,my_expiry_function,NULL);

//implementation
void my_expiry_function(struct k_timer *timer_id){
	printk("Timer expired\n");
}

void main(void)
{
	printk("Hello World! %s\n", CONFIG_BOARD);
	k_timer_start(&my_timer, K_MSEC(1000), K_MSEC(1000));
    return;
}

처음에 timer를 선언했고 expiry_function도 등록했어.

그리고 main 함수에서 timer를 시작하고 return!

말 그대로 main함수를 종료시켜버린거지.

그래도? 타이머는 아주 자알~~ 돈다~

👇👇

Timer

타이머 선언할 때 콜백이 하나 더 있었어.

타이머 중지 콜백인데.

이건 타이머가 수행중에 사용자에 의해 중지되면 동작하는 콜백이야.

 

이것도 예제를 살펴보자구.

👇👇

#include <zephyr/kernel.h>

//declaration
void my_expiry_function(struct k_timer *timer_id);
void my_timer_stop_function(struct k_timer *timer_id);

//타이머 만료 콜백 함수와 타이머 중지 콜백 함수를 등록
K_TIMER_DEFINE(my_timer,my_expiry_function,my_timer_stop_function);

//implementation
void my_expiry_function(struct k_timer *timer_id){
	printk("Timer expired\n");
}

void my_timer_stop_function(struct k_timer *timer_id){
	printk("Timer stopped\n");
}

void main(void)
{
	printk("Hello World! %s\n", CONFIG_BOARD);
	k_timer_start(&my_timer, K_MSEC(1000), K_MSEC(1000));
	k_sleep(K_SECONDS(2.5));
	printk("Timer will be stopped: %d\n",k_timer_remaining_get(&my_timer));
	k_timer_stop(&my_timer);
	return;
}

my_timer_stop_function이라는 콜백 함수를 작성하고

그걸 K_TIMER_DEFINE 매크로에 등록했어.

그리고 메인문에서 1초 반복 타이머를 시작하고 2.5초 뒤에 중지시켰어.

그러면 500ms 정도 타이머가 진행된 상태에서 타이머 중지 콜백이 호출될거야.

👇👇

타이머 중지 콜백도 잘 동작한다.

이렇게 편하게 타이머를 쓸 수 있다니 ㅎㅎ 너무 좋아~으흐흐흐

 

한 가지만 더 해볼 게 있는데

k_timer_status_sync()라는 함수야.

이 함수는 타이머가 만료되어 콜백이 수행되기 전까지 thread가 멈춰있게 해.

void main(void)
{
	printk("Hello World! %s\n", CONFIG_BOARD);
	k_timer_start(&my_timer, K_MSEC(1000), K_MSEC(1000));
	for(;;){
		k_timer_status_sync(&my_timer);
		printk("After timer expired.\n");
	}
}

이런식으로 thread가 timer expiry callback에 의존하게 할 수 있지.

역시나? 자알~~ 동작한다~

k_timer_status_sync() 동작

별거 아닌거 같아도 내가 원할 때 딱딱 쓰려면 많이 익숙해져야 해 ㅎㅎ

그러니까 비슷한 예제 10번 정도는 반복해서 돌려보자 ㅋ

그래봐야 30분 안걸려!

안녕

👋👋👋

 

2023.06.03 - [임베디드 소프트웨어/Zephyr] - [nRF52840 + Zephyr] #11. Inter-task communication A

 

[nRF52840 + Zephyr] #11. Inter-task communication A

제퍼의 경우에는 Inter-thread communication이 되겠구만! 지원되는 기능을 살펴보니.... 너무 많아;;;😢 👇👇 우린 너무 많은 거 안좋아 하니까 줄여보자구. 난 보통 다른 RTOS에서는 Flag와 Queue를 많이

engschool.tistory.com

 

반응형