VPOS_kernel_main() 에서 부터, shell thread 가 수행되기전까지의 설명을 담고 있다.

VPOS_kernel_main

수행에 필요한 queue 와 하드웨어 초기화를 수행한다. 마지막으로 가장 낮은 우선순위를 가지는 shell thread 를 수행하고, 스케줄러를 시작한다.

void VPOS_kernel_main( void )
{
  pthread_t p_thread;
 
  vk_init_kdata_struct();  // 앞으로의 수행에 필요한 각 queue 생성 및 초기화
  vk_machine_init();       // 하드웨어 설정 초기화
 
  printk("%s\n%s\n%s\n%s\n%s\n%s\n", top_line, version, develop, release, homepage, bottom_line);
  pthread_create(&p_thread, NULL, VPOS_SHELL, (void *)NULL);     // 기본적인 shell thread 생성
 
  VPOS_start();     // 스케줄러 동작
}

각 queue 를 생성하고 초기화 시킨다. vpos 는 총 0 ~ 31 단계의 우선순위를 가질 수 있다. 그래서 각각 31 개의 queue 를 생성한다.

void vk_init_kdata_struct(void)
{
  vk_init_ready_queue();    // ready queue (0 ~ 31개)
  vk_init_wait_queue();     // wait queue  (0 ~ 31개)
  vk_init_tcb_log_queue();  // tcb log queue  (0 ~ 31개)
  vk_init_dd_table();       // device driver, 총 29 개의 vk_dd_table 생성 및 총 64 개의 vk_idt_table 생성
  vk_init_thread_join_table();     // 10 개의 thread_join_table 생성
  vk_current_thread= &init_thread;   // init thread 를 current thread 로 지정
}

각각의 하드웨어 초기화를 한다.

void vk_machine_init(void)
{
	vh_serial_init();   // 시리얼 통신을 위한 UART 관련 레지스터 세팅(s3c2410 user manual 참조)
	vh_timer_init();   // 타이머 등록 및 인터럽트 언마스크
 
	vh_rtc_init();
	vh_lcd_init();
}

위에서 vh_timer_init() 의 타이머를 등록시키는 루틴을 살펴보기로 한다.

void vh_timer_init(void)
{
	int timer_load_val;
	int TIMER = 14;
 
	vu_register_dev(0, "Timer", &timer_device_driver_fops, 14);   // file_operations(open, release, read, write, ioctl, interrrupt) 가진 구조체
	vh_interrupt_unmask(TIMER);
 
	vh_rTCFG0 = 0x0f00;  
	vh_rTCFG1 = 0x0000;	
	timer_load_val = 50000000/(2*16*100); 
	vh_rTCNTB = timer_load_val;  
	vh_rTCON = (vh_rTCON & ~0x0700000) | 0x600000; 
	vh_rTCON = (vh_rTCON & ~0x0700000) | 0x500000; 
}
...
...
...
 
int vu_register_dev(unsigned int dev_number, char *dev_name, struct file_operations *fops, int irq_num)
{
	unsigned int i;
 
	i = dev_number;   // i = 0
 
	if(vk_dd_table[i].register_dev == 1) {   // 이미 dev_number 를 사용하고 있다면
		printk("Alreday %s device driver is registered\n", dev_name);
		return -1;
	}
 
	vk_dd_table[i].register_dev = 1;
	vk_dd_table[i].name = dev_name;       //  Timer
	vk_dd_table[i].interrupt_number= irq_num;   //  14
	vk_dd_table[i].fop_list = fops;   //  file_operations(open, release, read, write, ioctl, interrrupt)
	if(irq_num >= 0) vk_idt_table[irq_num]=dev_number;   // vk_idt_table[14] = 0
	return 0;
}

위의 코드를 수행 후의 상태는 다음과 같다.

구조체 변수값
vk_dd_table[0] register_dev = 1
name = Timer
interrupt_number = 14
fop_list = file_operations
구조체 변수값
vk_idt_table[14] 0

여기서 fop_list 에 등록된 file_operations 은 다음과 같다. 아래에 보면, TIMER 인터럽트가 발생하면, vh_timer_interrupt_handler() 를 호출한다.

struct file_operations timer_device_driver_fops =
{
	NULL,  // open
	NULL,  // release
	NULL,  // read
	NULL,  // write
	NULL,  // ioctl
	vh_timer_interrupt_handler   // interrupt 발생 시 수행 함수
};

주기적으로 TIMER 인터럽트가 발생할 때마다 수행되는 함수는 아래와 같다.

int vh_timer_interrupt_handler(void)
{
	vh_rSRCPND = vh_BIT_TIMER;       // 레지스터 세팅
	vh_rINTPND = vh_BIT_TIMER;
 
	++(vk_current_thread->cpu_tick);    //  vk_current_thread->cpu_tick = 0  ->  1 
	if(vk_sched_lock==0) vk_scheduler();  //  vk_sched_lock = 0, vk_scheduler() 함수 호출
	return 0;
}

등록을 한 후에는 인터럽트를 언마스크 한다.

	vh_interrupt_unmask(TIMER);    // TIMER = 14
...
...
...
void vh_interrupt_unmask(int unmask_irq_number)
{
	vh_rINTMSK &= ~(0x1<<unmask_irq_number);   //  vh_rINTMSK = 0x4a000008, ~(0x1<<unmask_irq_number) = 0xFFFFBFF
}

s3c2410 user manual 을 보면(p358), 0x4a000008 에 0 은 마스크를 해제, 1 은 마스크를 적용하도록 설정할 수 있다. 여기서는 TIMER 의 인터럽트를 언마스크 해야 하기 때문에, 0x14 의 역수로 설정한다.
이 결과, 스케줄링은 타이머 인터럽트에 의해서 주기적으로 발생되며, 또는 사용자에 의한 함수 호출로 인해 발생할 수 있다는 것을 알았다.

루틴은 다음과 같다. 여기서는 시스템의 년, 월, 일을 설정한다.

void vh_rtc_init(void)
{
	int Timetick = 8;
 
	vu_register_dev(8, "Timetick", &timeTick_device_driver_fops, 8);  // Timetick 등록
	vh_interrupt_unmask(Timetick);     // 인터럽트 마스크 해제
	//sem_init(&time_sem, 0, 1);
 
	vh_rRTCCON  = 0x00;
	vh_rTICNT = (1<<7) + 127;
 
	vh_timeInit();
}

위 루틴의 수행 후의 상태는 다음과 같다.

구조체 변수값
vk_dd_table[8] register_dev = 1
name = Timetick
interrupt_number = 8
fop_list = file_operations
구조체 변수값
vk_idt_table[14] 8
  • computer/rtcclab/vpos_분석_-_2.부팅.txt
  • Last modified: 4 years ago
  • by likewind