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

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


개발 환경



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;
    }
}