[Embedded Software] 경희대 임베디드 소프트웨어 과제5 - Multitasking in uC/OS-II
개발 환경
- 개발보드 : JKIT-128-1
- MUC : ATmega128
- OS : uC/OS-II
- Editor : WinAVR Progrmmers Notepad
- Compiler : WinAVR
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);
}
}