[Embedded Software] 경희대 임베디드 소프트웨어 과제5 - Multitasking in uC/OS-II

경희대학교 컴퓨터공학과 조진성 교수님의 ‘임베디드 소프트웨어’ 강의의 과제입니다.


개발 환경



uC/OS-II


C 언어 기반으로 작성된 마이크로프로세서를 위한 저비용 우선순위 기반 선점형 실시간 운영체제 커널 위키백과


uC/OS-II File Structure


Task state Diagram in uC/OS-II



실습 내용


(1) LED task의 OSTimeDlyHMSM()을 _delay_ms()으로 교체 수행 결과 및 분석


동작하지 않는다.

_delay_ms()는 while 루프를 돌면서 잠시 멈추는 것이고, OSTimeDlyHMSM()은 테스크를 waiting 상태로 바꾸면서 멈추는 것이다. 따라서 _delay_ms()로 동작을 안 하는 것은 while(1)를 나가지 못하기 때문이다.

// LedTask 코드 부분
...

while(1) {
	// LED는 Output으로 사용되기 때문에 PORT를 사용한다.
	PORTA= 0xFF;
	_delay_ms(10000);
	PORTA= 0x00;
	_delay_ms(10000);
}
	
...


(2) FND task의 _delay_ms()를 OSTimeDlyHMSM()로 교체 수행 결과 및 분석


동작하지 않는다.

os_cfg.h 를 보면 OS_TICKS_PER_SEC 에 대한 정의가 100 으로 되어 있다.

// os_cfg.h
...

#define OS_TICK_STEP_EN		1    /* Enable tick stepping feature for uC/OS-View */
#define OS_TICKS_PER_SEC	100    /* Set the number of ticks in one second */

...

따라서, 이 보드는 1초에 100번의 ticks를 할 수 있고, 이는 OSTimeDlyHMSM()에 들어갈 수 있는 최소의 시간 단위는 10ms 라는 의미이다.

FND를 정상작동하려면 타임 딜레이를 아주 짧은 시간(10ms 보다 작은 시간)으로 해야 하기 때문에, 이 경우에는 OSTimeDlyHMSM()을 사용할 수 없다.


(3) LED task와 FND task의 우선순위를 교체 수행 결과 및 분석


동작하지 않는다.

FND task가 더 자주 호출되기 때문에 우선순위를 더 높게 두는 것이 맞지만, 지금과 같은 경우엔 LED task의 우선순위가 더 높게 되어야 한다.

왜냐하면 FND task에서는 OSTimeDlyHMSM()을 사용할 수 없기 때문에, _delay_ms()를 사용해야하며 FND task의 우선순위가 더 높다면 while(1)안의 _delay_ms()를 빠져나오지 못한다.  

따라서 OSTimeDlyHMSM()의 사용이 가능한 LED task의 우선순위를 더 높게 두고, 타임 인터럽트가 걸리면(타임 인터럽트는 10ms 간격으로 발생) LED task를 waiting 상태로 전환 후 FND task의 수행을 하며, FND task 수행 중에 waiting 하는 시간이 끝나면 다시 LED task의 수행이 되도록 한다.



실습 응용


Multitasking example without OS (LED와 FND를 Non-multitasking으로 구현)

#define F_CPU 16000000UL

#include <avr/io.h>
#include <util/delay.h>

volatile unsigned char FND_DATA[ ]= {
		0x3f, // 0
		0x06, // 1 
		0x5b, // 2 
		0x4f, // 3 
		0x66, // 4 
		0x6d, // 5 
		0x7d, // 6 
		0x27, // 7 
		0x7f, // 8 
		0x6f, // 9 
		0x77, // A 
		0x7c, // B 
		0x39, // C 
		0x5e, // D 
		0x79, // E 
		0x71, // F 
		0x80, // . 
		0x40, // - 
		0x08  // _
	};

volatile unsigned int num=0, num0, num1, num2, num3;

void main() {
	DDRA = 0xFF;
	DDRC = 0xFF;
	DDRG = 0x0F;
	
	while(1) {
		num++;
		num3 = (num / 1000) % 10; // 10s
		num2 = (num / 100) % 10; // 1s
		num1 = (num / 10) % 10; // 0.1s
		num0 = num % 10; // 0.01s

		// led
		if(num1 < 5) {
			PORTA = 0xAA;
		}
		else {
			PORTA = 0x55;
		}

		
		// fnd
		PORTC = FND_DATA[num3];
		PORTG = 0x08;	
		_delay_ms(2);
		
		PORTC = FND_DATA[num2] | FND_DATA[16];
		PORTG = 0x04;
		_delay_ms(3);
		
		PORTC = FND_DATA[num1];
		PORTG = 0x02;	
		_delay_ms(2);
		
		PORTC = FND_DATA[num0];
		PORTG = 0x01;
		_delay_ms(3);
	}
}