맨 처음에 event.h를 만들때

예약된 자리가 여러개 있었는데,

원래 책에서는 처음 event.h 만들면서 UartIN 플래그 이름만 붙여있었지만

나는 이 헤더파일을 깃헙 완성본에서 복붙하다보니까 이미 사용자 정의 이벤트 이름들이 다 붙어있다.

두번째 이벤트가 CmdIn인데 이걸로 이벤트 처리를 하도록 메인함수를 수정하자.

 

 

boot/Main.c

태스크 0은 유아트 입력 이벤트 처리 시에 커널 API로 커맨드 입력 이벤트를 보내는걸 추가하고

태스크 1은 커맨드 입력 이벤트를 읽어들이면 태스크 1이 이벤트 핸들링했다고 출력해주는 내용이다.

#include <stdint.h>
#include <stdbool.h>

#include "HalInterrupt.h"
#include "HalUart.h"
#include "HalTimer.h"

#include "task.h"
#include "Kernel.h"

#include "stdio.h"
#include "stdlib.h"

static void Hw_init(void);
static void Kernel_init(void);

static void	Printf_test(void);
static void Timer_test(void);

void User_task0(void);
void User_task1(void);
void User_task2(void);

void main(void)
{
	Hw_init();

	uint32_t i = 100;
	while(i--)
	{
		Hal_uart_put_char('N');
	}
	Hal_uart_put_char('\n');
	putstr("Hello World!\n");

	Printf_test();
	Timer_test();

	Kernel_init();
	
	while(true);
}

static void Hw_init(void)
{
	Hal_interrupt_init();
	Hal_uart_init();
	Hal_timer_init();
}

static void Printf_test(void)
{
	char* str = "printf pointer test";
	char* nullptr = 0;
	uint32_t i = 5;
	uint32_t* sysctrl0 = (uint32_t*)0x10001000;

	debug_printf("%s\b", "Hello printf");
	debug_printf("output string pointer: %s\n", str);
	debug_printf("%s is null pointer, %u number\n", nullptr, 10);
	debug_printf("%u=5\n", i);
	debug_printf("dec=%u hex=%x\n", 0xff, 0xff);
	debug_printf("print zero %u\n", 0);
	debug_printf("SYSCTRL0 %x\n", *sysctrl0);

}

static void Timer_test(void)
{
	for(uint32_t i = 0; i < 5 ; i++)
	{
		debug_printf("current count : %u\n", Hal_timer_get_1ms_counter());
		delay(1000);
	}
}

static void Kernel_init(void)
{
	uint32_t taskId;

	Kernel_task_init();
	Kernel_event_flag_init();

	taskId = Kernel_task_create(User_task0);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task0 creation fail\n");
	}

	taskId = Kernel_task_create(User_task1);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task1 creation fail\n");
	}

	taskId = Kernel_task_create(User_task2);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task2 creation fail\n");
	}

	Kernel_start();
}

void User_task0(void)
{
	uint32_t local = 0;
	
	debug_printf("User Task #0 SP = 0x%x\n", &local);

	while(true)
	{
		KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_UartIn);
		switch(handle_event)
		{
			case KernelEventFlag_UartIn:
				debug_printf("\nEvent handled\n");
				Kernel_send_events(KernelEventFlag_CmdIn);
				break;
		}
		Kernel_yield();
		delay(100);
	}
}

void User_task1(void)
{
	uint32_t local = 0;

	debug_printf("User Task #1 SP = 0x%x\n", &local);

	while(true)
	{
		KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_CmdIn);
		switch(handle_event)
		{
			case KernelEventFlag_CmdIn:
				debug_printf("\nEvent handled by Task1\n");
				break;
		}
		Kernel_yield();
		delay(100);
	}
}

void User_task2(void)
{
	uint32_t local = 0;

	while(true)
	{
		debug_printf("User Task #2 SP = 0x%x\n", &local);
		Kernel_yield();
		delay(100);
	}
}

 

 

 

태스크들이 동작중에 유아트 입력 인터럽트가 들어오면

인터럽트 핸들러가 처리 후. 이벤트를 보낸다.

 

태스크 0번 동작 때 유아트 입력 이벤트를 확인하고 이벤트 핸들링 한 후에 커맨드 입력 이벤트를 보낸다.

 

태스크 1번 동작 차례가되면 커맨드 입력 이벤트가 보내졌지 확인해 처리하면서

아래의 결과가 나온다.

 

 

여러 이벤트 플래그 동시 보내고 처리

 

이전 글에서 kernel/Kernel.c에 Kernel_send 웨이팅 이벤트 함수는

uint32_t 이벤트리스트를 인자로 전달하는데,

그냥 이벤트 플래그가 아니라 uint32_t인 이유는 or연산으로 여러 이벤트를 같이 보내도록 하기 위해서였다고 했다.

 

UART 입력 인터럽트 발생 시 유아트 입력과 커맨드 입력 이벤트

+ 입력된 값이 'x'인 경우 CmdOut 이벤트를 보내도록 인터럽트 핸들러를 수정하면

 

hal/rvpb/Uart.c

#include <stdint.h>
#include "Uart.h"
#include "HalUart.h"
#include "HalInterrupt.h"

#include "Kernel.h"

extern volatile PL011_t* Uart;

static void interrupt_handler(void);

void Hal_uart_init(void)
{
	//enable UART
	Uart->uartcr.bits.UARTEN=0;
	Uart->uartcr.bits.TXE=1;
	Uart->uartcr.bits.RXE=1;
	Uart->uartcr.bits.UARTEN=1;

	Uart->uartimsc.bits.RXIM=1;

	Hal_interrupt_enable(UART_INTERRUPT0);
	Hal_interrupt_register_handler(interrupt_handler, UART_INTERRUPT0);
}

void Hal_uart_put_char(uint8_t ch)
{
	while(Uart->uartfr.bits.TXFF);
	Uart->uartdr.all = (ch & 0xFF);
}

uint8_t Hal_uart_get_char(void)
{
	uint32_t data;

	while(Uart->uartfr.bits.RXFE);

	data = Uart->uartdr.all;

	//check for and error flag
	if (data & 0xFFFFFF00)
	{
		//clear the error
		Uart->uartrsr.all = 0xFF;
		return 0;
	}

	return (uint8_t)(data & 0xff);
}

static void interrupt_handler(void)
{
	uint8_t ch = Hal_uart_get_char();
	Hal_uart_put_char(ch);

	Kernel_send_events(KernelEventFlag_UartIn|KernelEventFlag_CmdIn);

	if (ch == 'x')
	{
		Kernel_send_events(KernelEventFlag_CmdOut);
	}
}

 

 

 

태스크 0은 유아트 입력, cmd out 이벤트 처리

태스크 1은 그대로 커맨드 입력 이벤츠 처리 하도록 된 메인함수 코드

 

boot/Main.c

#include <stdint.h>
#include <stdbool.h>

#include "HalInterrupt.h"
#include "HalUart.h"
#include "HalTimer.h"

#include "task.h"
#include "Kernel.h"

#include "stdio.h"
#include "stdlib.h"

static void Hw_init(void);
static void Kernel_init(void);

static void	Printf_test(void);
static void Timer_test(void);

void User_task0(void);
void User_task1(void);
void User_task2(void);

void main(void)
{
	Hw_init();

	uint32_t i = 100;
	while(i--)
	{
		Hal_uart_put_char('N');
	}
	Hal_uart_put_char('\n');
	putstr("Hello World!\n");

	Printf_test();
	Timer_test();

	Kernel_init();
	
	while(true);
}

static void Hw_init(void)
{
	Hal_interrupt_init();
	Hal_uart_init();
	Hal_timer_init();
}

static void Printf_test(void)
{
	char* str = "printf pointer test";
	char* nullptr = 0;
	uint32_t i = 5;
	uint32_t* sysctrl0 = (uint32_t*)0x10001000;

	debug_printf("%s\b", "Hello printf");
	debug_printf("output string pointer: %s\n", str);
	debug_printf("%s is null pointer, %u number\n", nullptr, 10);
	debug_printf("%u=5\n", i);
	debug_printf("dec=%u hex=%x\n", 0xff, 0xff);
	debug_printf("print zero %u\n", 0);
	debug_printf("SYSCTRL0 %x\n", *sysctrl0);

}

static void Timer_test(void)
{
	for(uint32_t i = 0; i < 5 ; i++)
	{
		debug_printf("current count : %u\n", Hal_timer_get_1ms_counter());
		delay(1000);
	}
}

static void Kernel_init(void)
{
	uint32_t taskId;

	Kernel_task_init();
	Kernel_event_flag_init();

	taskId = Kernel_task_create(User_task0);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task0 creation fail\n");
	}

	taskId = Kernel_task_create(User_task1);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task1 creation fail\n");
	}

	taskId = Kernel_task_create(User_task2);
	if (NOT_ENOUGH_TASK_NUM == taskId)
	{
		putstr("Task2 creation fail\n");
	}

	Kernel_start();
}

void User_task0(void)
{
	uint32_t local = 0;
	
	debug_printf("User Task #0 SP = 0x%x\n", &local);

	while(true)
	{
		KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_UartIn | KernelEventFlag_CmdOut);
		switch(handle_event)
		{
			case KernelEventFlag_UartIn:
				debug_printf("\nEvent handled by Task#0\n");
				Kernel_send_events(KernelEventFlag_CmdIn);
				break;
			case KernelEventFlag_CmdOut:
				debug_printf("\nCmdOut Event by Task0\n");
				break;
		}
		Kernel_yield();
		delay(100);
	}
}

void User_task1(void)
{
	uint32_t local = 0;

	debug_printf("User Task #1 SP = 0x%x\n", &local);

	while(true)
	{
		KernelEventFlag_t handle_event = Kernel_wait_events(KernelEventFlag_CmdIn);
		switch(handle_event)
		{
			case KernelEventFlag_CmdIn:
				debug_printf("\nEvent handled by Task1\n");
				break;
		}
		Kernel_yield();
		delay(100);
	}
}

void User_task2(void)
{
	uint32_t local = 0;

	while(true)
	{
		debug_printf("User Task #2 SP = 0x%x\n", &local);
		Kernel_yield();
		delay(100);
	}
}

 

 

키를 입력하면 기존 대로 동작하다가

x를 입력시에는

기존 대로

event handled task 0

event handled task 1 

출력 후

 

sEventFlag에 남아있던 CmdOut 플래그를 태스크 0번때 읽어들여

cmdout event by task0이 출력된다.

 

 

 

+ Recent posts