一步步写嵌入式操作系统-系统调用

系统调用的实现基础

用户应用程序(用户态)使用SWI指令触发arm软件异常中断,cpu进入管理模式(内核态)

基本思路

1.对内核系统调用编码,编写内核系统调用表

2.针对系统调用编写软件中断异常处理函数

3.编写与内核系统调用对应的系统调用接口

4.编译用户应用程序为elf

5.把用户应用程序写入vfs

6.用vfs制作磁盘镜像

7.运行os,在文件系统里找到用户应用程序运行

用户应用程序

user_system_call.h

// 供用户应用程序使用的系统调用接口

#ifndef _USER_SYSTEM_CALL_H_

#define _USER_SYSTEM_CALL_H_

#define SYSTEM_CALL_TYPE_PRINT 0    //系统调用类型:打印
#define SYSTEM_CALL_TYPE_IO    1    //系统调用类型:IO
#define SYSTEM_CALL_TYPE_NUM   2    //系统调用类型总数

#define SYSTEM_CALL_RET_ERE -1
#define SYSTEM_CALL_RET_SUC 0

// 系统调用宏
// 系统调用返回值:ret(r0)
// 传递给内核的系统调用类型号:type(立即数)
// 参数个数:argc(r1)
// 参数数组首地址:args(r2)
// %0:ret,%1:type,%2:argc,%3:args
#define SYSTEM_CALL(type,argc,args,ret) do { \
    asm volatile \
    ( \
        "stmfd r13!,{lr}\n" /*用户模式返回地址入栈,为了用户模式调用SYSTEM_CALL后可返回*/ \
        "mov r1,%2\n" \
        "mov r2,%3\n" \
        "swi %1\n" \
        "ldmfd r13!,{lr}\n" /*用户模式返回地址出栈,为了用户模式调用SYSTEM_CALL后可返回*/ \
        :"=r"(ret) \
        :"i"(type),"r"(argc),"r"(args) \
        : \
    ); \
}while(0);

#endif // _USER_SYSTEM_CALL_H_

user_main.c

#include "user_system_call.h"

int main(void)
{
    const char *string = "this is in user main\n";
    for (;;)
    {
        if (*string == '\0')
        {
            break;
        }
        *(volatile unsigned int *)0xd0000020 = *string; // leeos已开启mmu,串口虚拟地址为0xd0000020
        string++;
    }

    int ret = -1;
    SYSTEM_CALL(SYSTEM_CALL_TYPE_PRINT,3,(int *)30000000,ret);

    string = "SYSTEM_CALL_RETURNED\n";
    for (;;)
    {
        if (*string == '\0')
        {
            break;
        }
        *(volatile unsigned int *)0xd0000020 = *string;
        string ++;
    }
    
    return(0);
}

// arm-none-eabi-gcc -e main -nostartfiles -nostdlib -Ttext 0x30100000 -o user_main.elf user_main.c
// arm-none-eabi-objcopy -O binary user_main.elf user_main.bin

leeos工程源码

abnormal.s

.equ SYS_MOD,0x1f
.equ IRQ_MOD,0x12
.equ FIQ_MOD,0x11
.equ ABT_MOD,0x17
.equ UND_MOD,0x1b

.equ DISABLE_IRQ,0x80
.equ DISBALE_FIQ,0x40

.macro CHANGE_TO_SYS
	msr cpsr_c,#(DISABLE_IRQ | DISBALE_FIQ | SYS_MOD)
.endm

.macro CHANGE_TO_IRQ
	msr cpsr_c,#(DISABLE_IRQ | DISBALE_FIQ | IRQ_MOD)
.endm

.global __vector_undefined
.global __vector_swi
.global __vector_prefetch_abort
.global __vector_data_abort
.global __vector_reserved
.global __vector_irq
.global __vector_fiq

.extern handle_abnormal_undefined
.extern handle_abnormal_swi
.extern os_system_call
.extern handle_abnormal_prefetch
.extern handle_abnormal_data
.extern handle_abnormal_reserved

.text
.code 32

__vector_undefined:
	b handle_abnormal_undefined
__vector_swi:
	str lr,[r13,#-4]		@保存用户模式swi指令后一指令地址
	mrs r0,spsr			@取用户模式程序状态
	str r0,[r13,#-8]		@保存用户模式程序状态
	mov r0,r13			@取软件中断异常状态(管理模式)栈指针
	CHANGE_TO_SYS			@切换到系统模式(内核态)
	stmfd r13!,{r0}		@把管理模式栈指针压入系统模式栈
	ldr r0,[r0,#-4]		@取用户模式swi指令后一指令地址
	sub r0,r0,#4			@取用户模式swi指令地址
	ldr r0,[r0]			@取用户模式swi指令
	bic r0,r0,#0xff000000	@取swi指令的后24位(系统调用类型号)
	bl os_system_call		@系统调用
	ldmfd r13!,{r1}		@管理模式栈指针出栈到r1
	ldr r2,[r1,#-8]		@取用户模式程序状态
	msr cpsr,r2			@切换为用户模式程序状态
	ldr pc,[r1,#-4]		@取用户模式swi指令后一指令地址 
__vector_prefetch_abort:
	b handle_abnormal_prefetch
__vector_data_abort:
	b handle_abnormal_data
__vector_reserved:
	b handle_abnormal_reserved
__vector_irq:
sub lr,lr,#0x4
	stmfd sp!,{lr}
	bl common_irq_handler
	mrs lr,spsr
	msr cpsr_c,lr
	ldmfd sp!,{lr}
	mov pc,lr

__vector_fiq:
	nop

@ __vector_irq:
@ 	sub r14,r14,#4		@取被中断进程的返回地址
@ 	stmfd r13!,{r0}		@r0压入中断模式栈,被中断进程的args
@ 	stmfd r13!,{r1-r3}	@r3-r1压入中断模式栈

@ 	// 清空中断相关寄存器
@ 	mov r2,#0xca000000	@取中断控制器地址
@ 	add r1,r2,#0x10
@ 	ldr r0,[r1]
@ 	ldr r3,[r2]
@ 	orr r3,r3,r1
@ 	str r3,[r2]
@ 	str r0,[r1]

@ 	ldmfd r13!,{r1-r3}
@ 	mov r0,r14
@ 	CHANGE_TO_SYS
@ 	stmfd r13!,{r0}
@ 	stmfd r13!,{r14}
@ 	CHANGE_TO_IRQ
@ 	ldmfd r13!,{r0}
@ 	ldr r14,=__asm_schedule
@ 	stmfd r13!,{r14}
@ 	ldmfd r13!,{pc}^

@ __asm_schedule:
@ 	stmfd r13!,{r0-r12}
@ 	mrs	r1, cpsr
@ 	stmfd r13!,{r1}

@ 	mov	r1,sp
@ 	bic	r1,#0xff0
@ 	bic r1,#0xf
@ 	mov r0,sp
@ 	str r0,[r1]

@ 	bl __common_schedule
@ 	ldr sp,[r0]
@ 	ldmfd r13!,{r1}
@ 	msr cpsr_cxsf,r1
@ 	ldmfd r13!,{r0-r12,r14,pc}


@ __vector_irq:				@书里中断异常的复杂处理程序
@ 	sub r14,r14,#0x4
@ 	stmfd r13!,{r14}
@ 	mrs r14,spsr
@ 	stmfd r13!,{r14}
@ 	CHANGE_TO_SVC
@ 	stmfd r13!,{r0,r1,r2,r3}
@ 	bl common_irq_handler
@ 	ldmfd r13!,{r0,r1,r2,r3}
@ 	CHANGE_TO_IRQ
@ 	ldmfd r13!,{r14}
@ 	msr spsr,r14
@ 	ldmfd r13!,{pc}^

@ __vector_irq:					@书里优秀的中断异常处理程序
@ 	sub r14,r14,#0x4
@ 	str r14,[r13,#-0x4]
@ 	mrs r14,spsr
@ 	str r14,[r13,#-0x8]
@ 	str r0,[r13,#-0xc]
@ 	mov r0,r13
@ 	CHANGE_TO_SVC
@ 	str r14,[r13,#-0x8]!
@ 	ldr r14,[r0,#-0x4]
@ 	str r14,[r13,#-0x4]
@ 	ldr r14,[r0,#-0x8]
@ 	ldr r0,[r0,#-0xc]
@ 	stmdb r13!,{r0-r3,r14}
@ 	bl common_irq_handler
@ 	ldmia r13!,{r0-r3,r14}
@ 	msr spsr,r14
@ 	ldmfd r13!,{r14,pc}^

@ my__vector_swi:			@用以实现系统调用的软件中断异常处理程序
	@ str lr,[r13,#-4]		@保存用户模式swi指令后一指令地址
	@ mrs r0,spsr			@取用户模式程序状态
	@ str r0,[r13,#-8]		@保存用户模式程序状态
	@ mov r0,r13			@取软件中断异常状态(管理模式)栈指针
	@ CHANGE_TO_SYS			@切换到系统模式(内核态)
	@ stmfd r13!,{r0}		@把管理模式栈指针压入系统模式栈
	@ ldr r0,[r0,#-4]		@取用户模式swi指令后一指令地址
	@ sub r0,r0,#4			@取用户模式swi指令地址
	@ ldr r0,[r0]			@取用户模式swi指令
	@ bic r0,r0,#0xff000000	@取swi指令的后24位(系统调用类型号)
	@ bl os_system_call		@系统调用
	@ ldmfd r13!,{r1}		@管理模式栈指针出栈到r1
	@ ldr r2,[r1,#-8]		@取用户模式程序状态
	@ msr cpsr,r2			@切换为用户模式程序状态
	@ ldr pc,[r1,#-4]		@取用户模式swi指令后一指令地址 

start.s

.section .startup
.code 32
.align 0

.global _start
.extern __vector_reset
.extern __vector_undefined
.extern __vector_swi
.extern __vector_prefetch_abort
.extern __vector_data_abort
.extern __vector_reserved
.extern __vector_irq
.extern __vector_fiq

@程序入口地址_start
_start:
	ldr pc,_vector_reset			@pc = __vector_reset,处理复位异常
	ldr pc,_vector_undefined		@处理未定义异常
	ldr pc,_vector_swi				@处理软件中断异常
	ldr pc,_vector_prefetch_abort	@处理预取址中止异常
	ldr pc,_vector_data_abort		@处理数据中止异常
	ldr pc,_vector_reserved			@处理保留异常
	ldr pc,_vector_irq				@处理中断异常
	ldr pc,_vector_fiq				@处理快速中断异常

	.align 4

_vector_reset:			.word  __vector_reset
_vector_undefined:		.word  __vector_undefined
_vector_swi:			.word  __vector_swi
_vector_prefetch_abort:	.word  __vector_prefetch_abort
_vector_data_abort:		.word  __vector_data_abort
_vector_reserved:		.word  __vector_reserved
_vector_irq:			.word  __vector_irq
_vector_fiq:			.word  __vector_fiq

init.s

.equ DISABLE_IRQ,	0x80
.equ DISABLE_FIQ,	0x40
.equ SYS_MOD,		0x1f
.equ IRQ_MOD,		0x12
.equ FIQ_MOD,		0x11
.equ SVC_MOD,		0x13
.equ ABT_MOD,		0x17
.equ UND_MOD,		0x1b

.equ MEM_SIZE, 		0x800000
.equ TEXT_BASE,		0x30000000
.equ _SVC_STACK,	(TEXT_BASE + MEM_SIZE - 4)
.equ _IRQ_STACK,	(_SVC_STACK - 0x400)
.equ _FIQ_STACK,	(_IRQ_STACK - 0x400)
.equ _ABT_STACK,	(_FIQ_STACK - 0x400)
.equ _UND_STACK,	(_ABT_STACK - 0x400)
.equ _SYS_STACK,	(_UND_STACK - 0x400)

.text
.code 32
.global __vector_reset

.extern boot
.extern __bss_start__
.extern __bss_end__

@复位异常向量处理程序入口地址__vector_reset
__vector_reset:				
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | SVC_MOD)
	ldr sp,=_SVC_STACK
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | IRQ_MOD)
	ldr sp,=_IRQ_STACK
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | FIQ_MOD)
	ldr sp,=_FIQ_STACK
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | ABT_MOD)
	ldr sp,=_ABT_STACK
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | UND_MOD)
	ldr sp,=_UND_STACK
	msr cpsr_c,#(DISABLE_IRQ | DISABLE_FIQ | SYS_MOD)
	ldr sp,=_SYS_STACK

_clear_bss:
	ldr r1,_bss_start_
	ldr r3,_bss_end_
	mov r2,#0x0
_loop:
	cmp r1,r3
	beq boot
	str r2,[r1],#0x4
	b _loop

_bss_start_:	
	.word  __bss_start__
_bss_end_:		
	.word  __bss_end__

.end

types.h

#ifndef _TYPES_H_

#define _TYPES_H_

#define NULL (void *)0

#define ERR_RET -1
#define SUC_RET 0

#endif  // _TYPES_H_

boot.c

// 欢迎来到c代码的世界
#include "types.h"
#include "string.h"

extern void init_sys_mmu(void);
extern void start_mmu(void);
extern void printk(char *fmt,...);
extern void memory_test(void);
extern void RamDiskTest(void);
extern void vfs_test(void);
extern void excute_test_bin(void);
extern void excute_test_elf(void);

#define USART_PHYSICAL_ADDR	0x50000020
static void helloworld(void)
{
	const char *p = "helloworld\n";
	while(*p)
	{
		*(volatile unsigned int *)USART_PHYSICAL_ADDR = *p;
		p ++;
	};
}

void boot(void)
{
	helloworld();
	init_sys_mmu();
	start_mmu();
	// memory_test();
	//RamDiskTest();
	// vfs_test();
	// excute_test_bin();
	excute_test_elf();
	printk("in boot\n");
}

void handle_abnormal_undefined(void)
{
	printk("handle_abnormal_undefined\n");
	for (;;)
	{
		;
	}
}

void handle_abnormal_swi(void)
{
	printk("handle_abnormal_swi\n");
	for (;;)
	{
		;
	}
}

void handle_abnormal_prefetch(void)
{
	printk("handle_abnormal_prefetch\n");
	for (;;)
	{
		;
	}
}

void handle_abnormal_data(void)
{
	printk("handle_abnormal_data\n");
	for (;;)
	{
		;
	}
}


void handle_abnormal_reserved(void)
{
	printk("handle_abnormal_reserved\n");
	for (;;)
	{
		;
	}
}

mmu.c

// 段页表基址mask
#define PAGE_TABLE_L1_BASE_ADDR_MASK	(0xffffc000)
// 由虚拟地址到段页表项索引
#define VIRT_TO_PTE_L1_INDEX(addr)		(((addr) & 0xfff00000) >> 18)
// 段页表项表示的页不使用cache和write_buf
#define PTE_L1_SECTION_NO_CACHE_AND_WB	(0x0 << 2)
// 段页表项默认域标识
#define PTE_L1_SECTION_DOMAIN_DEFAULT	(0x0 << 5)
// 段页表项默认权限标识
#define PTE_ALL_AP_L1_SECTION_DEFAULT	(0x1 << 10)
// 段页表项获取物理地址mask
#define PTE_L1_SECTION_PADDR_BASE_MASK	(0xfff00000)
// 一级页表标识
#define PTE_BITS_L1_SECTION				(0x2)
// 段页表基地址
#define L1_PTR_BASE_ADDR				0x30700000

// 物理内存地址
#define PHYSICAL_MEM_ADDR				0x30000000
// 虚拟内存地址
#define VIRTUAL_MEM_ADDR				0x30000000
// 物理内存大小
#define MEM_MAP_SIZE					0x800000

// 物理外设地址
#define PHYSICAL_IO_ADDR				0x48000000
// 虚拟外设地址
#define VIRTUAL_IO_ADDR					0xc8000000
// 外设内存大小
#define IO_MAP_SIZE						0x18000000

// 异常向量虚拟地址
#define VECTOR_VIRTUAL_ADDR 			0x0
// 异常向量物理地址
#define VECTOR_PHYSICAL_ADDR			0x30000000
 
void start_mmu(void)
{
	unsigned int ttb = L1_PTR_BASE_ADDR;
 
	asm (
		"mcr p15,0,%0,c2,c0,0\n"    /* set base address of page table*/
		"mvn r0,#0\n"                  
		"mcr p15,0,r0,c3,c0,0\n"    /* enable all region access*/
 
		"mov r0,#0x1\n"
		"mcr p15,0,r0,c1,c0,0\n"    /* set back to control register */
		"mov r0,r0\n"
		"mov r0,r0\n"
		"mov r0,r0\n"
		:
		: "r" (ttb)
		:"r0"
	);
}
 
// 由物理内存获取段页表项
unsigned int gen_l1_pte(unsigned int paddr)
{
	return (paddr & PTE_L1_SECTION_PADDR_BASE_MASK) | PTE_BITS_L1_SECTION;
}
 
// 由段页表基地址和虚拟地址获取段页表项地址
unsigned int gen_l1_pte_addr(unsigned int baddr, unsigned int vaddr)
{
	return (baddr & PAGE_TABLE_L1_BASE_ADDR_MASK) | VIRT_TO_PTE_L1_INDEX(vaddr);
}
 
// 映射物理内存空间\外设内存空间到虚拟内存
void init_sys_mmu(void)
{
	unsigned int pte;
	unsigned int pte_addr;
	int j;

	// 异常向量表映射
	for (j = 0; j < MEM_MAP_SIZE >> 20; j ++)
	{
		pte = gen_l1_pte(VECTOR_PHYSICAL_ADDR + (j << 20));
		pte |= PTE_ALL_AP_L1_SECTION_DEFAULT;
		pte |= PTE_L1_SECTION_NO_CACHE_AND_WB;
		pte |= PTE_L1_SECTION_DOMAIN_DEFAULT;
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, VECTOR_VIRTUAL_ADDR + (j << 20));
		*(volatile unsigned int *)pte_addr = pte;
	}
 
	// 物理内存大小为8M,一级页表的页大小为1M,一共8页
	for(j = 0; j < MEM_MAP_SIZE >> 20; j ++) 
	{
		pte = gen_l1_pte(PHYSICAL_MEM_ADDR + (j << 20));
		pte |= PTE_ALL_AP_L1_SECTION_DEFAULT;
		pte |= PTE_L1_SECTION_NO_CACHE_AND_WB;
		pte |= PTE_L1_SECTION_DOMAIN_DEFAULT;
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, VIRTUAL_MEM_ADDR + (j << 20));
		*(volatile unsigned int *)pte_addr = pte;
	}

	// 外设地址空间映射到虚拟内存,0x180页
	for(j = 0; j < IO_MAP_SIZE >> 20; j ++) 
	{
		pte = gen_l1_pte(PHYSICAL_IO_ADDR+(j << 20));
		pte |= PTE_ALL_AP_L1_SECTION_DEFAULT;
		pte |= PTE_L1_SECTION_NO_CACHE_AND_WB;
		pte |= PTE_L1_SECTION_DOMAIN_DEFAULT;
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, VIRTUAL_IO_ADDR + (j << 20));
		*(volatile unsigned int *)pte_addr = pte;
	}
}

// 建立物理地址和虚拟地址bytes字节的映射关系
void mmu_remaping(unsigned int pAddr,unsigned int vAddr,unsigned int bytes)
{
	unsigned int pte;
	unsigned int pte_addr;
	int j;
	for(j = 0; j < (bytes >> 20); j ++) 
	{
		pte = gen_l1_pte(pAddr + (j << 20));
		pte_addr = gen_l1_pte_addr(L1_PTR_BASE_ADDR, vAddr + (j << 20));
		*(volatile unsigned int *)pte_addr = pte;
	}
}

void test_mmu(void)
{
	const char *p = "test_mmu\n";
	while (*p) 
	{
		*(volatile unsigned int *)0xd0000020 = *p;
		p ++;
	};
}

printk.c

#define PRINTK_BYTE_IO_VIRTUAL_ADDR 0xd0000020

#define PRINTK_IS_PRINTABLE(c)   ( ( (c >= 32) && (c <= 126) ) || (c == '\n') ) 
#define PRINTK_FMT_TYPE_FLAG '%'
#define PRINTK_FMT_TYPE_CHAR 'c'
#define PRINTK_FMT_TYPE_INT 'd'
#define PRINTK_FMT_TYPE_ADDR 'a'
#define PRINTK_FMT_TYPE_STRING 's'

#define PRINTK_PRINT_CHAR(c) do { \
	if (PRINTK_IS_PRINTABLE(c)) \
	{ \
		*(volatile unsigned int *)(PRINTK_BYTE_IO_VIRTUAL_ADDR) = c; \
	} \
}while(0);

#define PRINTK_STRUCT_BUF_SIZE 64
struct
{
	char buf[PRINTK_STRUCT_BUF_SIZE];
	unsigned int amount;
}printk_struct;

#define PRINTK_TEMP_STRUCT_BUF_SIZE 32
struct
{
	char buf[PRINTK_TEMP_STRUCT_BUF_SIZE];
	unsigned int amount;
}printk_temp_struct;

void printk_struct_buf_clear(void)
{
	unsigned int i = 0;
	for (i = 0; i < PRINTK_STRUCT_BUF_SIZE; i++)
	{
		printk_struct.buf[i] = '\0';
	}
	printk_struct.amount = 0;
}

void printk_temp_struct_buf_clear(void)
{
	unsigned int i = 0;
	for (i = 0; i < PRINTK_TEMP_STRUCT_BUF_SIZE; i++)
	{
		printk_temp_struct.buf[i] = '\0';
	}
	printk_temp_struct.amount = 0;
}

void printk_struct_buf_insert_tail(char c)
{
	if (PRINTK_IS_PRINTABLE(c))
	{
		if (printk_struct.amount < PRINTK_STRUCT_BUF_SIZE)
		{
			printk_struct.buf[printk_struct.amount] = c;
			printk_struct.amount++;
		}
	}
}

void printk_temp_struct_buf_insert_tail(char c)
{
	if (PRINTK_IS_PRINTABLE(c))
	{
		if (printk_temp_struct.amount < PRINTK_TEMP_STRUCT_BUF_SIZE)
		{
			printk_temp_struct.buf[printk_temp_struct.amount] = c;
			printk_temp_struct.amount++;
		}
	}
}

void printk_print_string(char *string)
{
	char *p = string;
	unsigned char i = 0;
	for (;;)
	{
		if (PRINTK_IS_PRINTABLE(p[i]))
		{
			PRINTK_PRINT_CHAR(p[i]);
		}
		else
		{
			break;
		}
		i++;
	}
}

unsigned int printk_get_string_length(char *string)
{
	char *p = string;
	unsigned int length = 0;
	for (;;)
	{
		if (PRINTK_IS_PRINTABLE(p[length]))
		{
			length++;
			continue;
		}
		else
		{
			return(length);
		}
	}
}

void printk_temp_struct_buf_reverse(void)
{
	unsigned int i = 0;
	char temp = '\0';
	for (i = 0; i < printk_temp_struct.amount; i++)
	{
		if (i >= (printk_temp_struct.amount - 1 - i))
		{
			break;
		}
		temp = printk_temp_struct.buf[i];
		printk_temp_struct.buf[i] = printk_temp_struct.buf[printk_temp_struct.amount - 1 - i];
		printk_temp_struct.buf[printk_temp_struct.amount - 1 - i] = temp;
	}
}

void printk_temp_struct_buf_fill_int(int num_int)
{
	int num_int_positve = 0;
	char result = '\0';
	if (num_int == 0)
	{
		printk_temp_struct_buf_insert_tail('0');
		return;
	}
	else if (num_int > 0)
	{
		num_int_positve = num_int;
	}
	else if (num_int < 0)
	{
		num_int_positve = -num_int;
	}
	
	for (;;)
	{
		if (num_int_positve == 0)
		{
			break;
		}
		result = (char)(num_int_positve % 10) + '0';
		printk_temp_struct_buf_insert_tail(result);
		num_int_positve = num_int_positve / 10;
	}
	if (num_int < 0)
	{
		printk_temp_struct_buf_insert_tail('-');
	}
	printk_temp_struct_buf_reverse();
}

void printk_struct_buf_append_temp_buf(void)
{
	unsigned int i = 0;
	char *p = printk_temp_struct.buf;
	for (i = printk_struct.amount;i < PRINTK_STRUCT_BUF_SIZE; i++)
	{
		if (PRINTK_IS_PRINTABLE(*p))
		{
			printk_struct_buf_insert_tail(*p);
		}
		else
		{
			break;
		}
		p++;
	}
}

void printk_temp_struct_buf_fill_addr(unsigned int num_addr)
{
	unsigned int addr = num_addr;
	char result = '\0';

	if (num_addr == 0)
	{
		printk_temp_struct_buf_insert_tail('0');
		return;
	}

	for (;;)
	{
		if (addr == 0)
		{
			break;
		}
		result = (char)(addr % 10) + '0';
		printk_temp_struct_buf_insert_tail(result);
		addr = addr / 10;
	}
	printk_temp_struct_buf_reverse();
}

void printk_temp_struct_buf_fill_string(unsigned int char_addr)
{
	char *p = (char *)char_addr;
	for (;;)
	{
		if (PRINTK_IS_PRINTABLE(*p))
		{
			printk_temp_struct_buf_insert_tail(*p);
		}
		else
		{
			break;
		}
		p++;
	}
}


#define PRINTK_INIT_PARGV(pArgv,fmt) ( pArgv = (char *)&fmt )
#define PRINTK_REFRESH_PARGV(pArgv) ( pArgv = pArgv + 4 )
#define PRINTK_GET_ARGV(pArgv,type) ( *(type *)pArgv )
#define PRINTK_DEINIT_PARGV(pArgv) ( pArgv = (char*)0 )
void printk_struct_buf_format(char *pV,char *fmt)
{
	char *pArgv = pV;
	char *format = fmt;
	unsigned int format_length = 0;
	unsigned int i = 0;
	format_length = printk_get_string_length(format);
	for (i = 0; i < format_length; i++)
	{
		if (format[i] == PRINTK_FMT_TYPE_FLAG)
		{
			if (format[i + 1] == PRINTK_FMT_TYPE_CHAR)
			{
				PRINTK_REFRESH_PARGV(pArgv);
				char c = PRINTK_GET_ARGV(pArgv,char);
				printk_struct_buf_insert_tail(c);
				i++;
			}
			else if (format[i + 1] == PRINTK_FMT_TYPE_INT)
			{
				printk_temp_struct_buf_clear();
				PRINTK_REFRESH_PARGV(pArgv);
				int num_int = PRINTK_GET_ARGV(pArgv,int);
				printk_temp_struct_buf_fill_int(num_int);
				printk_struct_buf_append_temp_buf();
				i++;
			}
			else if (format[i + 1] == PRINTK_FMT_TYPE_ADDR)
			{
				printk_temp_struct_buf_clear();
				PRINTK_REFRESH_PARGV(pArgv);
				unsigned int num_addr = PRINTK_GET_ARGV(pArgv,unsigned int);
				printk_temp_struct_buf_fill_addr(num_addr);
				printk_struct_buf_append_temp_buf();
				i++;
			}
			else if (format[i + 1] == PRINTK_FMT_TYPE_STRING)
			{
				printk_temp_struct_buf_clear();
				PRINTK_REFRESH_PARGV(pArgv);
				unsigned int char_addr = PRINTK_GET_ARGV(pArgv,unsigned int);
				printk_temp_struct_buf_fill_string(char_addr);
				printk_struct_buf_append_temp_buf();
				i++;
			}
			else
			{
				printk_struct_buf_insert_tail(format[i]);
			}
		}
		else
		{
			printk_struct_buf_insert_tail(format[i]);
		}
	}

}

void printk(char *fmt,...)
{
	printk_struct_buf_clear();
	char *pArgv;
	PRINTK_INIT_PARGV(pArgv,fmt);
	printk_struct_buf_format(pArgv,fmt);
	printk_print_string(printk_struct.buf);
	PRINTK_DEINIT_PARGV(pArgv);
}

void test_printk(void)
{
	printk("test_printk start\n");
	int x;
	printk("[char:%c,int:%d,int:%d,int:%d,address:%a,address:%a,string:%s]\n",'a',123,-123,0,0,&x,"hello_printk");
	printk("test_printk end\n");
}

string.h

#ifndef _STRING_H_

#define _STRING_H_

extern int memncpy(void *srcAddr,void *desAddr,unsigned int nBytes);
extern int memnset(void *addr,char c,unsigned int bytes);
extern int memncmp(void *p1,void *p2,unsigned int bytes);

extern unsigned int strlen(char *string);

// --------------------------------------------------
extern void memncpy_test(void);
extern void memnset_test(void);
extern void memncmp_test(void);
extern void strlen_test(void);

#endif // _STRING_H_

string.c

#include "string.h"
#include "types.h"

extern void printk(char *fmt,...);

int memncpy(void *srcAddr,void *desAddr,unsigned int nBytes)
{
    if ((srcAddr == NULL) || (desAddr == NULL))
    {
        return(ERR_RET);
    }
    unsigned int i = 0;
    for (i = 0; i < nBytes; i ++)
    {
        // printk("srcAddr[i]:%c\n",*((char *)srcAddr + i));
        *((char *)(desAddr) + i) = *((char *)srcAddr + i);
    }
    return(SUC_RET);
}

int memnset(void *addr,char c,unsigned int bytes)
{
    if ((addr == NULL) || (c < 0))
    {
        return(ERR_RET);
    }
    unsigned int i = 0;
    for (i = 0; i < bytes; i ++)
    {
        *((char *)addr + i) = c;
    }
    return(SUC_RET);
}

int memncmp(void *p1,void *p2,unsigned int bytes)
{
    if ((p1 == NULL) || (p2 == NULL))
    {
        return(ERR_RET);
    }
    unsigned int i = 0;
    for (i = 0; i < bytes; i ++)
    {
        if ( (*((char *)p1 + i)) != (*((char *)p2 + i)) )
        {
            return(ERR_RET);
        }
    }
    return(SUC_RET);
}

unsigned int strlen(char *string)
{
    if (string == NULL)
    {
        return(ERR_RET);
    }
    unsigned int n = 0;
    for (;;)
    {
        if (*((char *)(string + n)) == '\0')
        {
            return(n);
        }
        n ++;
    }
}

// --------------------------------------------------
// buf2:hello
// pass
void memncpy_test(void)
{
    char buf1[] = "hello";
    char buf2[6];
    int ret = ERR_RET;
    ret = memncpy(buf1,buf2,5);
    if (ret == ERR_RET)
    {
        printk("memncpy error\n");
        return;
    }
    printk("buf2:%s\n",buf2);
}

// after memnset buf:aaaaaaa
// pass
void memnset_test(void)
{
	char buf[8];
	int ret = ERR_RET;
	ret = memnset(buf,'a',7);
	if (ret == ERR_RET)
	{
		printk("memnset error\n");
        return;
	}
    printk("after memnset buf:%s\n",buf);
}

void memncmp_test(void)
{

}

interrupt.c

// 中断基址
#define INT_BASE    (0xca000000)
// 中断屏蔽器
#define INT_MASK    (INT_BASE + 0x8)
// timer4的偏移值
#define INTOFFSET   (INT_BASE + 0x14)
// 通过屏蔽的中断寄存器
#define INTPND      (INT_BASE + 0x10)
// 主中断源寄存器,标识哪个硬件产生了中断
#define SRCPND      (INT_BASE + 0x0)

extern void printk(char *fmt,...);
// 中断公共处理函数
void common_irq_handler(void)
{
    // unsigned int tmp = (1 << (*(volatile unsigned int *)INTOFFSET));
    // printk("%d\n",*(volatile unsigned int *)INTOFFSET);
    // *(volatile unsigned int *)SRCPND |= tmp;
    // *(volatile unsigned int *)INTPND |= tmp;
    // printk("timer alarming\n");
}

// 定时器基址
#define TIMER_BASE      (0xd1000000)
// 一级分频器
#define TCFG0           ((volatile unsigned int *)(TIMER_BASE + 0x0))
// 二级分频器
#define TCFG1           ((volatile unsigned int *)(TIMER_BASE + 0x4))
// 定时控制器
#define TCON            ((volatile unsigned int *)(TIMER_BASE + 0x8))
// timer4减数器
#define TCONB4          ((volatile unsigned int *)(TIMER_BASE + 0x3c))

// 使能中断
void enable_irq(void)
{
    asm volatile
    (
        "mrs r4,cpsr\t\n"
        "bic r4,r4,#0x80\t\n"
        "msr cpsr,r4\t\n"
        :
        :
        :"r4"
    );
}

// 失能某个中断屏蔽位
void umask_int(unsigned int offset)
{
    *(volatile unsigned int *)INT_MASK &= ~(1 << offset);
}

// 定时器初始化
void timer_init(void)
{
    *TCFG0 |= 0x800;
    *TCON &= (~(7 << 20));
    *TCON |= (1 << 22);
    *TCON |= (1 << 21);
    *TCONB4 = 10000;
    *TCON |= (1 << 20);
    *TCON &= ~(1 << 21);
    umask_int(14);
    enable_irq();
}

memory.c

// 内存管理

#include "types.h"
extern void printk(char *fmt,...);

#define MEMORY_END_VIRTUAL_ADDR     0x30700000
#define MEMORY_START_VIRTUAL_ADDR   0x300f0000
// 待管理空间,6356992字节
#define MEMORY_BYTES                ( MEMORY_END_VIRTUAL_ADDR - MEMORY_START_VIRTUAL_ADDR )           

// 页表大小4k字节
#define MEMORY_PAGE_BYTES   (4 * 1024)

#define MEMORY_PAGE_FLAG_IDLE 0x0
#define MEMORY_PAGE_FLAG_BUSY 0x1
#define MEMORY_PAGE_FLAG_DIRTY 0x2
// 页表描述体
struct memory_page
{
    unsigned int vAddr;
    unsigned int flag;
    struct memory_page *pNextPage;
};
// 页表描述体大小
#define MEMORY_PAGE_DESCRIPTOR_BYTES    ( sizeof(struct memory_page) )
// 页表描述体起始虚拟地址
#define MEMORY_PAGE_DESCRIPTOR_START_VIRTUAL_ADDR MEMORY_START_VIRTUAL_ADDR

// 页表总个数,6356992/(4*1024+12)=1547
#define MEMORY_PAGE_NUM ( (MEMORY_END_VIRTUAL_ADDR - MEMORY_START_VIRTUAL_ADDR) / (MEMORY_PAGE_BYTES +MEMORY_PAGE_DESCRIPTOR_BYTES ) )
// 页表起始地址
#define MEMORY_PAGE_START_VIRTUAL_ADDR ( MEMORY_START_VIRTUAL_ADDR + MEMORY_PAGE_DESCRIPTOR_BYTES * MEMORY_PAGE_NUM )

#define MEMORY_BUDDY_TYPE_64K   (64 * 1024)
#define MEMORY_BUDDY_TYPE_128K  (128 * 1024)
#define MEMORY_BUDDY_TYPE_256K  (256 * 1024)
#define MEMORY_BUDDY_TYPE_512K  (512 * 1024)
#define MEMORY_BUDDY_TYPE_1024K (1024 * 1024)
#define MEMORY_BUDDY_TYPE_NUM   5
#define MEMORY_IS_BUDDY_TYPE(type) ( \
                                        (type == MEMORY_BUDDY_TYPE_64K) || \
                                        (type == MEMORY_BUDDY_TYPE_128K) || \
                                        (type == MEMORY_BUDDY_TYPE_256K) || \
                                        (type == MEMORY_BUDDY_TYPE_512K) || \
                                        (type == MEMORY_BUDDY_TYPE_1024K) \
                                    )

// buddy描述体
struct memory_buddy
{
    unsigned int type;
    unsigned int num;
    struct memory_page *pFirstPage;
};
// buddy池
static struct memory_buddy buddy[MEMORY_BUDDY_TYPE_NUM];

static inline void memory_init_all_page(void)
{
    unsigned int i = 0;
    struct memory_page *pPage = NULL;
    for (i = 0; i < MEMORY_PAGE_NUM; i ++)
    {
        pPage = (struct memory_page *)MEMORY_PAGE_DESCRIPTOR_START_VIRTUAL_ADDR + i;
        pPage->vAddr = MEMORY_PAGE_START_VIRTUAL_ADDR + i * MEMORY_PAGE_BYTES;
        pPage->flag = MEMORY_PAGE_FLAG_IDLE;
        pPage->pNextPage = NULL;
        // printk("i:%a,vAddr:%a\n",i,pPage->vAddr);
    }
}

static inline void memory_init_all_buddy(void)
{
    unsigned int i = 0;
    struct memory_page *pPage = NULL;

    buddy[0].type = MEMORY_BUDDY_TYPE_64K;
    buddy[0].num = 0;
    buddy[0].pFirstPage = NULL;

    buddy[1].type = MEMORY_BUDDY_TYPE_128K;
    buddy[1].num = 0;
    buddy[1].pFirstPage = NULL;

    buddy[2].type = MEMORY_BUDDY_TYPE_256K;
    buddy[2].num = 0;
    buddy[2].pFirstPage = NULL;

    buddy[3].type = MEMORY_BUDDY_TYPE_512K;
    buddy[3].num = 0;
    buddy[3].pFirstPage = NULL;

    // 1547个4k的page可生成6个1024k的buddy
    // 6个1024k的buddy利用了1536个4k的page
    buddy[4].type = MEMORY_BUDDY_TYPE_1024K;
    buddy[4].num = 6;
    buddy[4].pFirstPage = (struct memory_page *)MEMORY_PAGE_DESCRIPTOR_START_VIRTUAL_ADDR;
    pPage = buddy[4].pFirstPage;
    for (i = 0; i < buddy[4].num * (buddy[4].type / MEMORY_PAGE_BYTES); i ++)
    {
        // printk("i:%a,page vAddr:%a\n",i,pPage->vAddr);
        pPage->flag = MEMORY_PAGE_FLAG_BUSY;
        if (i == buddy[4].num * (buddy[4].type / MEMORY_PAGE_BYTES) - 1)
        {
            pPage->pNextPage = NULL;
        }
        else
        {
            pPage->pNextPage = pPage + 1;
            pPage = pPage->pNextPage;
        }
    }
}

// 分配指定的buddy
static inline struct memory_page *memory_malloc_buddy_p(struct memory_buddy *buddyAddr)
{
    if (buddyAddr == NULL)
    {
        return(NULL);
    }

    struct memory_page *pPage = NULL;
    struct memory_buddy *pBuddy = buddyAddr;

    // 无指定的buddy
    if (pBuddy->num < 1)
    {
        return(NULL);
    }
    // 有一个指定的buddy
    else if (pBuddy->num == 1)
    {
        pPage = pBuddy->pFirstPage;
        for (;;)
        {
            if (pPage == NULL)
            {
                break;
            }
            pPage->flag = MEMORY_PAGE_FLAG_DIRTY;
            pPage = pPage->pNextPage;
        }
        pPage = pBuddy->pFirstPage;
        pBuddy->pFirstPage = NULL;
        pBuddy->num = 0;
        return(pPage);
    }
    // 有多个指定的buddy
    else if (pBuddy->num > 1)
    {
        pPage = (pBuddy->pFirstPage) + (pBuddy->num - 1) * (pBuddy->type / MEMORY_PAGE_BYTES) - 1;
        pPage->pNextPage = NULL;
        pPage = (pBuddy->pFirstPage) + (pBuddy->num - 1) * (pBuddy->type / MEMORY_PAGE_BYTES);
        for (;;)
        {
            if (pPage == NULL)
            {
                break;
            }
            pPage->flag = MEMORY_PAGE_FLAG_DIRTY;
            pPage = pPage->pNextPage;
        }
        pPage = (pBuddy->pFirstPage) + (pBuddy->num - 1) * (pBuddy->type / MEMORY_PAGE_BYTES);
        pBuddy->num --;
        return(pPage);
    }
}
static inline struct memory_page *memory_malloc_buddy_recurse(struct memory_buddy *buddyAddr)
{
    if (buddyAddr == NULL)
    {
        return(NULL);
    }

    struct memory_page *pFirstPage = NULL;
    struct memory_buddy *pBuddy = buddyAddr;

    // 若当前大小的buddy个数大于1
    if (pBuddy->num >= 1)
    {
        pFirstPage = memory_malloc_buddy_p(pBuddy);
        return(pFirstPage);
    }
    // 若当前大小的buddy个数等于0
    else if (pBuddy->num == 0)
    {
        // 递归分配大小高一级的buddy
        pFirstPage = memory_malloc_buddy_recurse(pBuddy + 1);
        // 分配大小高一级的buddy失败
        if (pFirstPage == NULL)
        {
            return(NULL);
        }
        // 分配大小高一级的buddy成功
        else
        {
            pBuddy->pFirstPage = pFirstPage;
            pBuddy->num = (pBuddy->num) + 2;
            pFirstPage = memory_malloc_buddy_p(pBuddy);
            return(pFirstPage);
        }
    }
}
static inline struct memory_page *memory_malloc_buddy(unsigned int type)
{
    struct memory_page *pHeadPage = NULL;
    switch (type)
    {
        case MEMORY_BUDDY_TYPE_64K:
            pHeadPage = memory_malloc_buddy_recurse(&buddy[0]);
            break;
        case MEMORY_BUDDY_TYPE_128K:
            pHeadPage = memory_malloc_buddy_recurse(&buddy[1]);
            break;
        case MEMORY_BUDDY_TYPE_256K:
            pHeadPage = memory_malloc_buddy_recurse(&buddy[2]);
            break;
        case MEMORY_BUDDY_TYPE_512K:
            pHeadPage = memory_malloc_buddy_recurse(&buddy[3]);
            break;
        case MEMORY_BUDDY_TYPE_1024K:
            pHeadPage = memory_malloc_buddy_recurse(&buddy[4]);
            break;
        default:
            break;
    }
    return(pHeadPage);
}
// 获取由pFirstPage指定的buddy的大小类型
static inline unsigned int memory_get_buddy_type(struct memory_page *pFirstPage)
{
    if (pFirstPage == NULL)
    {
        return(0);
    }
    if (((pFirstPage + (MEMORY_BUDDY_TYPE_64K / MEMORY_PAGE_BYTES) - 1)->pNextPage) == NULL)
    {
        return(MEMORY_BUDDY_TYPE_64K);
    }
    if (((pFirstPage + (MEMORY_BUDDY_TYPE_128K / MEMORY_PAGE_BYTES) - 1)->pNextPage) == NULL)
    {
        return(MEMORY_BUDDY_TYPE_128K);
    }
    if (((pFirstPage + (MEMORY_BUDDY_TYPE_256K / MEMORY_PAGE_BYTES) - 1)->pNextPage) == NULL)
    {
        return(MEMORY_BUDDY_TYPE_256K);
    }
    if (((pFirstPage + (MEMORY_BUDDY_TYPE_512K / MEMORY_PAGE_BYTES) - 1)->pNextPage) == NULL)
    {
        return(MEMORY_BUDDY_TYPE_512K);
    }
    if (((pFirstPage + (MEMORY_BUDDY_TYPE_1024K / MEMORY_PAGE_BYTES) - 1)->pNextPage) == NULL)
    {
        return(MEMORY_BUDDY_TYPE_1024K);
    }
}
// 将由pFirstPage指定的buddy追加到pBuddy尾部
static inline void memory_append_buddy(struct memory_buddy *pBuddy,struct memory_page *pFirstPage)
{
    if ((pBuddy == NULL) || (pFirstPage == NULL))
    {
        return;
    }
    if (pBuddy->num == 0)
    {
        pBuddy->pFirstPage = pFirstPage;
        pBuddy->num ++;
    }
    else if (pBuddy->num > 0)
    {
        (pBuddy->pFirstPage + ((pBuddy->num) *  (pBuddy->type) / MEMORY_PAGE_BYTES - 1))->pNextPage = pFirstPage;
        pBuddy->num ++;
    }
}
// 释放由pFirstPage指定的buddy
static inline void memory_free_buddy(struct memory_page *pFirstPage)
{
    if (pFirstPage == NULL)
    {
        return;
    }
    struct memory_page *pTmpPage = pFirstPage;
    unsigned int buddyType = memory_get_buddy_type(pFirstPage);
    if (!MEMORY_IS_BUDDY_TYPE(buddyType))
    {
        return;
    }
    // 设置每个待释放的page的flag
    for (;;)
    {
        if (pTmpPage == NULL)
        {
            break;
        }
        pTmpPage->flag = MEMORY_PAGE_FLAG_BUSY;
        pTmpPage = pTmpPage->pNextPage;
    }

    // 将待释放的page加到对应的buddy尾部
    if (buddyType == MEMORY_BUDDY_TYPE_64K)
    {
        memory_append_buddy(&buddy[0],pFirstPage);
    }
    else if (buddyType == MEMORY_BUDDY_TYPE_128K)
    {
        memory_append_buddy(&buddy[1],pFirstPage);
    }
    else if (buddyType == MEMORY_BUDDY_TYPE_256K)
    {
        memory_append_buddy(&buddy[2],pFirstPage);
    }
    else if (buddyType == MEMORY_BUDDY_TYPE_512K)
    {
        memory_append_buddy(&buddy[3],pFirstPage);
    }
    else if (buddyType == MEMORY_BUDDY_TYPE_1024K)
    {
        memory_append_buddy(&buddy[4],pFirstPage);
    }

    // 较小的两块buddy合并为一块较大的buddy
    unsigned int i = 0;
    for (i = 0;i < MEMORY_BUDDY_TYPE_NUM - 1; i ++)
    {
        if (buddy[i].num == 2)
        {
            pTmpPage = buddy[i].pFirstPage;
            buddy[i].pFirstPage = NULL;
            buddy[i].num = 0;
            memory_append_buddy(&buddy[i + 1],pTmpPage);
        }
    }
}

static inline void memory_print_buddy(void)
{
    int i = 0;
    for (i = 0; i < MEMORY_BUDDY_TYPE_NUM; i ++)
    {
        printk("type:%a,num:%a\n",buddy[i].type,buddy[i].num);
    }
}

// 由指定字节数分配buddy,实际返回构成该buddy的第一个page的虚拟地址
void *memory_malloc(unsigned int bytes)
{
    struct memory_page *pPage = NULL;
    if ((bytes > 0) && (bytes <= MEMORY_BUDDY_TYPE_64K))
    {
        pPage = memory_malloc_buddy(MEMORY_BUDDY_TYPE_64K);
        return((void *)(pPage->vAddr));
    }
    else if ((bytes > MEMORY_BUDDY_TYPE_64K) && (bytes <= MEMORY_BUDDY_TYPE_128K))
    {
        pPage = memory_malloc_buddy(MEMORY_BUDDY_TYPE_128K);
        return((void *)(pPage->vAddr));
    }
    else if ((bytes > MEMORY_BUDDY_TYPE_128K) && (bytes <= MEMORY_BUDDY_TYPE_256K))
    {
        pPage = memory_malloc_buddy(MEMORY_BUDDY_TYPE_256K);
        return((void *)(pPage->vAddr));
    }
    else if ((bytes > MEMORY_BUDDY_TYPE_256K) && (bytes <= MEMORY_BUDDY_TYPE_512K))
    {
        pPage = memory_malloc_buddy(MEMORY_BUDDY_TYPE_512K);
        return((void *)(pPage->vAddr));
    }
    else if ((bytes > MEMORY_BUDDY_TYPE_512K) && (bytes <= MEMORY_BUDDY_TYPE_1024K))
    {
        pPage = memory_malloc_buddy(MEMORY_BUDDY_TYPE_1024K);
        return((void *)(pPage->vAddr));
    }
    else
    {
        return(NULL);
    }
}

// 根据page的虚拟地址释放buddy
void memory_free(void *vAddr)
{
    // page的虚拟地址
    unsigned int pageAddr = (unsigned int)vAddr;
    // 对应的首个page描述体地址
    struct memory_page *pPage;
    unsigned int i = 0;
    for (i = 0; i < MEMORY_PAGE_NUM; i ++)
    {
        pPage = (struct memory_page *)MEMORY_PAGE_DESCRIPTOR_START_VIRTUAL_ADDR + i;
        if (pPage->vAddr == pageAddr)
        {
            break;
        }
    }
    memory_free_buddy(pPage);
}

void memory_init(void)
{
    memory_init_all_page();
    memory_init_all_buddy();
}

void memory_test(void)
{
    // printk("MEMORY_PAGE_NUM:%a\n",MEMORY_PAGE_NUM);
    
    memory_init();
    memory_print_buddy();
    struct memory_page *pPage1 = NULL;
    pPage1 = memory_malloc_buddy(MEMORY_BUDDY_TYPE_1024K);
    memory_print_buddy();

    struct memory_page *pPage2 = NULL;
    pPage2 = memory_malloc_buddy(MEMORY_BUDDY_TYPE_64K);
    memory_print_buddy();

    struct memory_page *pPage3 = NULL;
    pPage3 = memory_malloc_buddy(MEMORY_BUDDY_TYPE_256K);
    memory_print_buddy();

    struct memory_page *pPage4 = NULL;
    pPage4 = memory_malloc_buddy(MEMORY_BUDDY_TYPE_256K);
    memory_print_buddy();

    char *p1 = (char *)memory_malloc(100 * 1024);
    if (p1 == NULL)
    {
        printk("memory_malloc return NULL\n");
        return;
    }
    memory_print_buddy();
    memory_free(p1);
    memory_print_buddy();
}

storage.h

#ifndef _STORAGE_H_

#define _STORAGE_H_

// 存储设备最大个数
#define STORAGE_DEVICE_NUM_MAX  1

// 存储设备描述体
typedef struct storage_device
{
    // 存储设备的虚拟地址
    unsigned int vAddr;
    // 存储容量
    unsigned int storageBytes;
    // 触发读写的最小字节数
    unsigned int baseBytes;
    // 从存储设备读出数据的函数指针
    int (*DoOut)(struct storage_device *pDevice,unsigned int offset,void *buf,unsigned int bytes);
    // 往存储设备写入数据的函数指针
    int (*DoIn)(struct storage_device *pDevice,unsigned int offset,void *buf,unsigned int bytes);
}sd_t;

// 注册存储设备函数
extern int StorageRegister(sd_t *pDevice,int no);

// 去注册存储设备函数(指定编号)
extern int StorageUnregister(int no);

// 外部可访问的存储设备指针数组
extern sd_t *pStorageDeviceArray[STORAGE_DEVICE_NUM_MAX];

#endif // _STORAGE_H_

storage.c

#include "types.h"
#include "storage.h"

// 外部可访问的存储设备指针数组
sd_t *pStorageDeviceArray[STORAGE_DEVICE_NUM_MAX];

// 注册存储设备函数
int StorageRegister(sd_t *pDevice,int no)
{
    if ((pDevice == NULL) || (no < 0 ) || (no >= STORAGE_DEVICE_NUM_MAX))
    {
        return(ERR_RET);
    }
    pStorageDeviceArray[no] = pDevice;
    return(SUC_RET);
}

// 去注册存储设备函数(指定编号)
int StorageUnregister(int no)
{
    if ((no < 0 ) || (no >= STORAGE_DEVICE_NUM_MAX))
    {
        return(ERR_RET);
    }
    pStorageDeviceArray[no] = NULL;
    return(SUC_RET);
}

ram_disk.c

#include "types.h"
#include "storage.h"
#include "string.h"

extern void printk(char *fmt,...);
extern void mmu_remaping(unsigned int pAddr,unsigned int vAddr,unsigned int bytes);

// 使用ram模拟的disk的在存储设备指针数组的编号
#define RAM_DISK_NO 0

// 使用ram模拟的disk描述体(外部可访问)
sd_t ramDisk;

static int RamDiskDoIn(sd_t *pRam,unsigned int offset,void *buf,unsigned int bytes)
{
    if ((pRam == NULL) || (buf == NULL))
    {
        return(ERR_RET);
    }
    if (bytes < (pRam->baseBytes))
    {
        return(ERR_RET);
    }
    int ret = ERR_RET;
    ret = memncpy(buf,(char *)(pRam->vAddr + offset),bytes);
    return(ret);
}

static int RamDiskDoOut(sd_t *pRam,unsigned int offset,void *buf,unsigned int bytes)
{
    if ((pRam == NULL) || (buf == NULL))
    {
        return(ERR_RET);
    }
    if (bytes < (pRam->baseBytes))
    {
        return(ERR_RET);
    }
    int ret = ERR_RET;
    ret = memncpy((char *)(pRam->vAddr + offset),buf,bytes);
    return(ret);
}


int RamDiskInit(void)
{
    int ret = ERR_RET;
    ramDisk.vAddr = 0x40800000;
    ramDisk.storageBytes = 2 * 1024 * 1024;
    ramDisk.baseBytes = 1;
    ramDisk.DoIn = RamDiskDoIn;
    ramDisk.DoOut = RamDiskDoOut;
    // printk("ramDisk.vAddr:%a\n",ramDisk.vAddr);
    mmu_remaping(0x30800000,0x40800000,ramDisk.storageBytes);
    ret = StorageRegister(&ramDisk,RAM_DISK_NO);
    return(ret);
}

int RamDiskRead(unsigned int offset,void *buf,unsigned int bytes)
{
    if (buf == NULL)
    {
        return(ERR_RET);
    }
    int ret = ERR_RET;
    ret = ramDisk.DoOut(&ramDisk,offset,buf,bytes);
    return(ret);
}

int RamDiskWrite(unsigned int offset,void *buf,unsigned int bytes)
{
    if (buf == NULL)
    {
        return(ERR_RET);
    }
    int ret = ERR_RET;
    ret = ramDisk.DoIn(&ramDisk,offset,buf,bytes);
    return(ret);
}

void RamDiskTest(void)
{
    int ret = ERR_RET;
    ret = RamDiskInit();
    if (ret != SUC_RET)
    {
        printk("RamDiskInit error\n");
        return;
    }
    printk("RamDiskInit success\n");

    char buf[64];
    ret = RamDiskRead(0,buf,64);
    if (ret != SUC_RET)
    {
        printk("RamDiskRead error\n");
        return;
    }
    printk("read buf:%s\n",buf);
    
    // char *s = "hello_ramdisk";
    // ret = memncpy(s,buf,13);
    // if (ret != SUC_RET)
    // {
    //     printk("memcpy error\n");
    //     return;
    // }
    // ret = RamDiskWrite(0,buf,64);
    // if (ret != SUC_RET)
    // {
    //     printk("RamDiskWrite error\n");
    //     return;
    // }
    // ret = RamDiskRead(0,buf,64);
    // if (ret != SUC_RET)
    // {
    //     printk("RamDiskRead error\n");
    //     return;
    // }
    // printk("read:%s\n",buf);
}

file_system.h

#ifndef _FILE_SYSTEM_H_

#define _FILE_SYSTEM_H_

#include "storage.h"

// 文件系统最大个数
#define FS_NUM_MAX              1

struct inode;
// 文件系统描述体
typedef struct super_block
{
    // 文件系统名
    char *name;
    // 文件系统存储设备
    struct storage_device *pDevice;
    // 通过inode获取数据地址的函数指针
    unsigned int (*GetDataAddr)(struct inode *pInode);
    // 通过文件名获取inode的函数指针
    struct inode *(*NameToInode)(char *name);
}fs_t;

// 文件描述体
typedef struct inode
{
    // 文件名
    char *name;
    // 控制标识
    unsigned int flags;
    // 文件的数据大小
    unsigned int size;
    // 文件数据地址(相对设备地址)
    unsigned int offset;
    // 文件所属的文件系统的指针
    struct super_block *pFs;
}file_t;

// 注册文件系统
int FsRegister(fs_t *pFs,int no);

// 去注册文件系统
int FsUnregister(int no);

// 打印文件系统名
void FsPrint(void);

// 外部可访问的文件系统指针数组
extern fs_t *pFsArray[FS_NUM_MAX];

#endif // _FILE_SYSTEM_H_

file_system.c

#include "types.h"
#include "file_system.h"

extern void printk(char *fmt,...);

fs_t *pFsArray[FS_NUM_MAX];

// 注册文件系统
int FsRegister(fs_t *pFs,int no)
{
    if ((pFs == NULL) || (no < 0) || (no >= FS_NUM_MAX))
    {
        return(ERR_RET);
    }
    pFsArray[no] = pFs;
    return(SUC_RET);
}

// 去注册文件系统
int FsUnregister(int no)
{
    if ((no < 0) || (no >= FS_NUM_MAX))
    {
        return(ERR_RET);
    }
    pFsArray[no] = NULL;
    return(SUC_RET);
}

// 打印文件系统名
void FsPrint(void)
{
    unsigned int i = 0;
    for (i = 0; i < FS_NUM_MAX; i ++)
    {
        if ((pFsArray[i]->name) == NULL)
        {
            printk("index:%a,file_system:NULL\n",i);
        }
        else
        {
            printk("index:%a,file_system:%s\n",i,pFsArray[i]->name);
        }
    }
}

vfs.c

#include "types.h"
#include "storage.h"
#include "file_system.h"
#include "string.h"

extern int RamDiskInit(void);
extern void memory_init(void);
extern void printk(char *fmt,...);
extern void *memory_malloc(unsigned int bytes);
extern void memory_free(void *p);
void vfs_print(void);

extern sd_t ramDisk;

// ----------------------------------------------
// vfs存储结构
// vfs文件系统头
// 文件:文件头,文件数据
#define VFS_FLAG "-vfsvfs-"
#define VFS_NAME_BYTES  8
// 文件系统头
typedef struct vfs_head
{
    // 文件系统名
    char name[VFS_NAME_BYTES];
    // 磁盘存储的文件数
    unsigned int fileNum;
}vfs_head_t;

#define VFS_FILE_NAME_BYTES 16
// 文件头
typedef struct vfs_file_head
{
    // 文件名
    char name[VFS_FILE_NAME_BYTES];
    // 文件字节数
    unsigned int bytes;
}vfs_file_head_t;
// ----------------------------------------------

fs_t vFS;
// LFS文件系统描述体在文件系统指针数组里的编号
#define VFS_NO  0
// LFS文件系统文件数量
static unsigned int vfsFileNum;
// LFS文件系统文件描述体指针
static file_t *pVFSInode;

static inline struct inode *VFSNameToInode(char *name)
{
    if (name == NULL)
    {
        return(NULL);
    }
    unsigned int i = 0;
    unsigned int n = 0;
    for (i = 0; i < vfsFileNum; i ++)
    {
        n = strlen(name);
        if (memncmp(name,pVFSInode[i].name,n) == SUC_RET)
        {
            return(&pVFSInode[i]);
        }
    }
    return(NULL);
}

static inline unsigned int VFSGetDataAddr(struct inode *pInode)
{
    if (pInode == NULL)
    {
        return(0);
    }
    return(pInode->offset + (vFS.pDevice)->vAddr);
}

// VFS文件系统初始化
int VFSInit(void)
{
    int ret = ERR_RET;
    unsigned int i = 0;
    unsigned int j = 0;

    // ramDisk盘初始化(VFS存放在ramDisk盘)
    ret = RamDiskInit();
    if (ret != SUC_RET)
    {
        printk("[VFSInit],RamDiskInit error\n");
        return(ERR_RET);
    }
    printk("RamDiskInit success\n");

    // 文件系统的文件依赖memory功能
    memory_init();
    printk("memory_init success\n");

    // 初始化vFS
    vFS.pDevice = &ramDisk;
    vFS.NameToInode = VFSNameToInode;
    vFS.GetDataAddr = VFSGetDataAddr;
    vFS.name = (char *)memory_malloc(VFS_NAME_BYTES + 1);
    if (vFS.name == NULL)
    {
        printk("[VFSInit],vFS.name memory_malloc error\n");
        return(ERR_RET);
    }

    ret = memnset(vFS.name,'\0',VFS_NAME_BYTES + 1);
    if (ret != SUC_RET)
    {
        printk("[VFSInit],vFS.name memnset error\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }

    ret = memncpy("vfs",vFS.name,3);
    if (ret != SUC_RET)
    {
        printk("[VFSInit],vFS.name memncpy error\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }
    // printk("vFS.name:%s\n",vFS.name);
    printk("init vFS success\n");

    // 判断磁盘里是否为vfs
    vfs_head_t *pVFSHead = (vfs_head_t *)((vFS.pDevice)->vAddr);
    // printk("(vFS.pDevice)->vAddr:%a\n",(vFS.pDevice)->vAddr);
    // printk("pVFSHead:%a\n",pVFSHead);

    ret = memncmp(pVFSHead->name,VFS_FLAG,VFS_NAME_BYTES);
    if (ret == ERR_RET)
    {
        printk("not vfs in disk\n");
        memory_free(vFS.name);
        return(ERR_RET);
    }
    printk("vfs in disk\n");

    vfsFileNum = pVFSHead->fileNum;
    printk("vfsFileNum:%a\n",vfsFileNum);
    
    if (vfsFileNum >= 1)
    {
        pVFSInode = (file_t *)memory_malloc(sizeof(file_t) * vfsFileNum);
        if (pVFSInode == NULL)
        {
            printk("memory_malloc error\n");
            memory_free(vFS.name);
            return(ERR_RET);
        }
        // printk("pVFSInode:%a\n",pVFSInode);

        vfs_file_head_t *pVFSFileHead = (vfs_file_head_t *)((char *)pVFSHead + sizeof(vfs_head_t));
        // printk("pVFSFileHead:%a\n",pVFSFileHead);

        for (i = 0; i < vfsFileNum; i ++)
        {
            // 设置inode属于的文件系统
            pVFSInode[i].pFs = &vFS;

            // 为inode的文件名分配空间
            pVFSInode[i].name = (char *)memory_malloc(VFS_FILE_NAME_BYTES + 1);
            if (pVFSInode[i].name == NULL)
            {
                printk("memory_malloc error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name malloc success\n",i);

            ret = memnset(pVFSInode[i].name,'\0',VFS_FILE_NAME_BYTES + 1);
            if (ret != SUC_RET)
            {
                printk("memnset error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name memnset success\n",i);

            // 获取文件名
            ret = memncpy(pVFSFileHead->name,pVFSInode[i].name,VFS_FILE_NAME_BYTES);
            if (ret != SUC_RET)
            {
                printk("memncpy error,i:%a\n",i);
                // 释放已经分配的inode的名字内存
                for (j = 0; j < i; j ++)
                {
                    memory_free(pVFSInode[j].name);
                }
                memory_free(pVFSInode);
                pVFSInode = NULL;
                memory_free(vFS.name);
                vFS.name = NULL;
                return(ERR_RET);
            }
            printk("inode[%a] name memncpy success\n",i);
            // printk("pVFSInode[%a].name:%s\n",i,pVFSInode[i].name);

            // printk("pVFSFileHead->bytes:%a\n",pVFSFileHead->bytes);

            pVFSInode[i].offset = (unsigned int)((char *)pVFSFileHead + sizeof(vfs_file_head_t) - (char *)pVFSHead);
            pVFSInode[i].size = pVFSFileHead->bytes;
            pVFSInode[i].flags = (unsigned int)0;
            
            pVFSFileHead = (vfs_file_head_t *)((char *)pVFSFileHead + sizeof(vfs_file_head_t) + (pVFSFileHead->bytes));
        }
    }

    // 注册LFS文件系统
    ret = FsRegister(&vFS,VFS_NO);
    if (ret != SUC_RET)
    {
        printk("FsRegister error\n");
        for(i = 0; i < vfsFileNum; i ++)
        {
            memory_free(pVFSInode[i].name);
            memory_free(&pVFSInode[i]);
        }
        memory_free(vFS.name);
    }
    printk("vfs registered\n");

    vfs_print();
    
    return(SUC_RET);
}

void vfs_print(void)
{
    unsigned int i = 0;
    for (i = 0; i < vfsFileNum; i ++)
    {
        printk("i:%a,name:%s,bytes:%a,offset:%a,addr:%a\n",i,pVFSInode[i].name,pVFSInode[i].size,pVFSInode[i].offset,vFS.GetDataAddr(&pVFSInode[i]));
    }
}

void vfs_test(void)
{
    int ret = ERR_RET;
    ret = VFSInit();
    if (ret != SUC_RET)
    {
        printk("VFSInit error\n");
        return;
    }

    vfs_print();
}

excute.c

#include "types.h"
#include "file_system.h"
#include "elf.h"

extern fs_t vFS;

extern int VFSInit(void);
extern void printk(char *fmt,...);
extern int memncpy(void *srcAddr,void *desAddr,unsigned int nBytes);

#define EXCUTE_ADDR 0x30100000
int excute(unsigned int addr)
{
    asm volatile
    (
        "mov pc,r0\n\t"
    );

    printk("main returned\n");

    return(0);
}

void excute_test_bin(void)
{
    int ret = -1;
    file_t *pFile = NULL;

    ret = VFSInit();
    if (ret == ERR_RET)
    {
        printk("VFSInit error\n");
        return;
    }
    printk("VFSInit success\n");

    pFile = vFS.NameToInode("user_main.bin");
    if (pFile == NULL)
    {
        printk("vFS.NameToInode error\n");
        return;
    }
    printk("vFS.NameToInode sucess\n");

    ret = memncpy((char *)(vFS.GetDataAddr(pFile)),(char *)EXCUTE_ADDR,pFile->size);
    if (ret == ERR_RET)
    {
        printk("memncpy error\n");
        return;
    }
    printk("memncpy success\n");

    excute(EXCUTE_ADDR);

    return;
}

void excute_test_elf(void)
{
    int ret = -1;
    file_t *pFile = NULL;
    struct elf32_ehdr *pELF32Head = NULL;
    struct elf32_phdr *pELF32ProgramHead = NULL;
    unsigned int i = 0;

    ret = VFSInit();
    if (ret == ERR_RET)
    {
        printk("VFSInit error\n");
        return;
    }
    printk("VFSInit success\n");

    pFile = vFS.NameToInode("user_main.elf");
    if (pFile == NULL)
    {
        printk("vFS.NameToInode error\n");
        return;
    }
    printk("vFS.NameToInode sucess\n");

   pELF32Head = (struct elf32_ehdr *)(vFS.GetDataAddr(pFile));
   pELF32ProgramHead = (struct elf32_phdr *)((char *)pELF32Head + pELF32Head->e_phoff);

    // printk("pELF32Head:%a\n",pELF32Head);
    // printk("vFS.GetDataAddr(pFile):%a\n",vFS.GetDataAddr(pFile));
    // printk("pELF32Head->e_phoff:%a\n",pELF32Head->e_phoff);
    // printk("pELF32ProgramHead:%a\n",pELF32ProgramHead);
    // printk("pELF32Head->e_phnum:%a\n",pELF32Head->e_phnum);

    for (i = 0; i < pELF32Head->e_phnum; i ++)
    {
        // printk("i:%a\n",i);
        // printk("pELF32ProgramHead->p_type:%d\n",pELF32ProgramHead->p_type);

        if (pELF32ProgramHead->p_type == PT_LOAD)
        {
                
            ret = memncpy((char *)pELF32Head + pELF32ProgramHead->p_offset,(char *)(pELF32ProgramHead->p_vaddr),pELF32ProgramHead->p_filesz);
            if (ret == ERR_RET)
            {
                printk("%a,memncpy error\n",i);
                return;
            }
            printk("%a,memncpy success\n",i);
            pELF32ProgramHead ++;
        }
    }

    // printk("pELF32Head->e_entry:%a\n",pELF32Head->e_entry);
    excute(pELF32Head->e_entry);

    return;
}

os_system_call.c

// 内核系统调用调度

#include "types.h"

extern void printk(char *fmt,...);

#define SYSTEM_CALL_TYPE_PRINT 0    //系统调用类型:打印
#define SYSTEM_CALL_TYPE_IO    1    //系统调用类型:IO
#define SYSTEM_CALL_TYPE_NUM   2    //系统调用类型总数

#define SYSTEM_CALL_RET_ERE -1
#define SYSTEM_CALL_RET_SUC 0

// 内核系统调用执行函数的类型
// 返回值类型为:int
// num:传递给内核系统调用执行函数的参数个数
// args:传递内核系统调用执行函数的参数指针
typedef int (*system_call_fun_t)(int argc,int *args);

// ----------系统调用类型执行函数声明开始---------- //
int OSPrint(int argc,int *args);
int OSIO(int argc,int *args);
// ----------系统调用类型执行函数声明结束---------- //

// 系统调用执行函数表
system_call_fun_t systemCallTalbe[SYSTEM_CALL_TYPE_NUM] = {
    (system_call_fun_t)OSPrint,
    // (system_call_fun_t)OSIO,
    NULL,
};

// 系统调用调度
// type:系统调用函数表的索引值,系统调用号
// argc:传递给系统调用执行函数的参数个数
// args:传递给系统调用执行函数的参数指针
int os_system_call(int type,int argc,int *args)
{
    printk("[os_system_call],type:%d,argc:%d,args:%a\n",type,argc,args);
    if (systemCallTalbe[type])
    {
        return((systemCallTalbe[type])(argc,args));
    }
}

int OSPrint(int argc,int *args)
{
    printk("this in OSPrint,argc:%d,args:%a\n",argc,args);
    return(SYSTEM_CALL_RET_SUC);
}

leeos.lds

OUTPUT_ARCH(arm)
ENTRY(_start)

SECTIONS
{
	. = 0x00000000;
	.text :
	{
		*(.startup)
		*(.text)
	}
	. = ALIGN(32);
	.data :
	{
		*(.data)
	}
	. = ALIGN(32);
	__bss_start__ = .;
	.bss :
	{
		*(.bss)
	}
	__bss_end__ = .;
}

makefile

CC = arm-none-eabi-gcc
LD = arm-none-eabi-ld
OBJCOPY = arm-none-eabi-objcopy

CFLAGS = -O0 -g
ASFLAGS = -O0 -g
LDFLAGS = -T leeos.lds -Ttext 30000000 

OBJS = abnormal.o start.o init.o boot.o \
		mmu.o \
	   	printk.o \
	   	string.o \
	   	interrupt.o \
    	memory.o \
	   	storage.o \
	   	ram_disk.o \
 	   	file_system.o \
 	   	vfs.o \
	   	excute.o \
	   	os_system_call.o \

.c.o:
	$(CC) $(CFLAGS) -c $<
.s.o:
	$(CC) $(ASFLAGS) -c $<

leeos.elf:$(OBJS)
	$(CC) -static -nostartfiles -nostdlib $(LDFLAGS) $? -o $@
	$(OBJCOPY) -O binary $@ leeos.bin

clean:
	rm -f *.o leeos.elf leeos.bin

skyeye.conf

cpu:  arm920t
mach: s3c2410x

#physical memory
#memroy bar
mem_bank: map = M, type = RW, addr = 0x30000000, size = 0x00800000, file = ./leeos.bin, boot = yes
#ramdisk
mem_bank: map = M, type = RW, addr = 0x30800000, size = 0x00200000, file = ./ramdisk.img
#io
mem_bank: map = I, type = RW, addr = 0x48000000, size = 0x20000000

运行效果

一步步写嵌入式操作系统-系统调用_第1张图片

 

你可能感兴趣的:(一步步写嵌入式操作系统,arm,开源,c语言,arm开发)