[Embedded Software] 경희대 임베디드 소프트웨어 과제4 - uC/OS-II Programming
on Study
개발 환경
- 개발보드 : JKIT-128-1
- MUC : ATmega128
- OS : uC/OS-II
- Editor : WinAVR Progrmmers Notepad
- Compiler : WinAVR
uC/OS-II
C 언어 기반으로 작성된 마이크로프로세서를 위한 저비용 우선순위 기반 선점형 실시간 운영체제 커널 위키백과
uC/OS-II File Structure
실습 응용
실습1.3 LED 하나씩 건너서 켜기/끄기와 실습3.1 FND를 이용하여 특정 숫자 표시를 uC/OS-II task로 구현
전체 소스코드 보기 (Github Repository - lab5)
Makefile
// https://github.com/sauber92/MicroC-OS-II_atmega128_multiprogramming/blob/master/lab5/app/Makefile
...
# Where uC/OS-II and the port are
# For *nix systems you can use something like the next two lines if you
# have uC/OS-II v2.70
# UCOSDIR = $(wildcard ~/Micrium/Software/uCOS-II/)
# PORTDIR = $(wildcard ~/Micrium/Software/uCOS-II/Ports/AVR/ATmega128/GNU/jlu)
# If you have uC/OS-II v2.52, use
# UCOSDIR = $(wildcard ~/ucos-II/software/uCOS-II/Source)
# PORTDIR = $(wildcard ~/Micrium/Software/uCOS-II/Ports/AVR/ATmega128/GNU/jlu)
# With Windows, use something like the next lines
UCOSDIR = c:[소스가 들어있는 디렉토리]/lab5/source
PORTDIR = c:[소스가 들어있는 디렉토리]/lab5/ports
INCDIR1 = $(UCOSDIR)
INCDIR2 = $(PORTDIR)
...
# Define directories, if needed.
DIRAVR = c:/[WinAVR 디렉토리 위치]
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
...
os_cfg.h
// https://github.com/sauber92/MicroC-OS-II_atmega128_multiprogramming/blob/master/lab5/app/os_cfg.h
...
#ifndef OS_CFG_H
#define OS_CFG_H
#define CPU_CLOCK_HZ 16000000
// Stack Size를 디폴트 값으로 128 지정
#define OS_TASK_DEF_STK_SIZE 128 /* Default stack size */
// 이 설정들에서 Disable(0) 하면 메모리 공간이 더 많아지나
// 체크를 안 한다는 단점이 있다.
/* ---------------------- MISCELLANEOUS ----------------------- */
#define OS_ARG_CHK_EN 0 /* Enable (1) or Disable (0) argument checking */
#define OS_CPU_HOOKS_EN 1 /* uC/OS-II hooks are found in the processor port files */
#define OS_DEBUG_EN 1 /* Enable(1) debug variables */
#define OS_EVENT_NAME_SIZE 32 /* Determine the size of the name of a Sem, Mutex, Mbox or Q */
#define OS_LOWEST_PRIO 12 /* Defines the lowest priority that can be assigned ... */
/* ... MUST NEVER be higher than 63! */
#define OS_MAX_EVENTS 3 /* Max. number of event control blocks in your application */
#define OS_MAX_FLAGS 1 /* Max. number of Event Flag Groups in your application */
#define OS_MAX_MEM_PART 1 /* Max. number of memory partitions */
#define OS_MAX_QS 2 /* Max. number of queue control blocks in your application */
// Task의 최대 갯수
#define OS_MAX_TASKS 11 /* Max. number of tasks in your application, MUST be >= 2 */
#define OS_SCHED_LOCK_EN 1 /* Include code for OSSchedLock() and OSSchedUnlock() */
#define OS_TASK_IDLE_STK_SIZE OS_TASK_DEF_STK_SIZE
/* Idle task stack size (# of OS_STK wide entries) */
#define OS_TASK_STAT_EN 1 /* Enable (1) or Disable(0) the statistics task */
#define OS_TASK_STAT_STK_SIZE OS_TASK_DEF_STK_SIZE
/* Statistics task stack size (# of OS_STK wide entries) */
#define OS_TASK_STAT_STK_CHK_EN 1 /* Check task stacks from statistic task */
#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 */
...
lab5.c
// https://github.com/sauber92/MicroC-OS-II_atmega128_multiprogramming/blob/master/lab5/app/lab5.c
#include "includes.h"
#define F_CPU 16000000UL // CPU frequency = 16 Mhz
#include <avr/io.h>
#include <util/delay.h>
#define TASK_STK_SIZE OS_TASK_DEF_STK_SIZE
// Task Stack
OS_STK LedTaskStk[TASK_STK_SIZE];
OS_STK FndTaskStk[TASK_STK_SIZE];
// Task
void LedTask(void *data);
void FndTask(void *data);
int main (void) {
// 마이크로 C/OS-II 에서 사용할 기능 초기화
OSInit();
// 크리티컬 섹션을 보호하기 위한 부분
// 인터럽트를 Disable해서 Context-switching이 안 일어나게 하는 방법
// 싱글프로세스일 때 사용
OS_ENTER_CRITICAL();
// 타이머 레지스터 사용
TCCR0=0x07;
TIMSK=_BV(TOIE0);
TCNT0=256-(CPU_CLOCK_HZ/OS_TICKS_PER_SEC/ 1024);
// 크리티컬 섹션 끝
OS_EXIT_CRITICAL();
// OSTaskCreate(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio);
// void (*task)(void *pd) : Task 명
// void *pdata : Task의 파라미터
// OS_STK *ptos : Task가 사용할 Stack. Stack은 메모리 공간이므로 배열 형식
// INT8U prio : Task의 ID이자 우선순위. 0이 최고우선순위이며 Task마다 ID가 같을 수 없다.
OSTaskCreate(LedTask, (void *)0, (void *)&LedTaskStk[TASK_STK_SIZE - 1], 0);
OSTaskCreate(FndTask, (void *)0, (void *)&FndTaskStk[TASK_STK_SIZE - 1], 1);
// Dormant 상태에 있는 Task를 Ready 상태로 바꾼다
OSStart();
return 0;
}
// LED ON/OFF를 10101010과 01010101로 반복하는 Task
void LedTask (void *data) {
data = data;
// Main task
DDRA = 0xFF;
while (1) {
PORTA = 0xAA;
// OSTimeDlyHMSM(INT8U hours, INT8U minutes, INT8U seconds, INT16U milli);
// Micro C/OS-II에서 사용하는 Delay function
OSTimeDlyHMSM(0, 0, 0, 500);
PORTA = 0x55;
OSTimeDlyHMSM(0, 0, 0, 500);
}
}
// FND 4자리를 모두 8888로 디스플레이하는 Task
void FndTask(void * data) {
data = data;
unsigned char FND_DATA[ ]= {0x3F, 0x06, 0x5B, 0x4F, 0x66,
0x6D, 0x7D, 0x27, 0x7F, 0x6F,
0x77, 0x7C, 0x39, 0x5E, 0x79,
0x71, 0x80, 0x40, 0x08};
DDRC = 0xFF;
DDRG = 0x0F;
while(1) {
PORTC = FND_DATA[8];
PORTG = 0x0f;
}
}