一步步写嵌入式操作系统 伙伴算法与内存管理

基本思路:

1.待管理的内存划分为标识区和供外部使用区,标识区用以描述和组织外部使用区。

2.外部使用区划分为基本单位(page),每个基本单位的大小为4Kbytes。

3.若干个page组成一个buddy,buddy按大小分成几类,如64k的buddy,128k的buddy,256k的buddy,512k的buddy,1024k的buddy

4.分配内存时根据申请分配的字节数自动更新各种buddy的数量,并返回合适的buddy。

5.释放内存时自动更新各种buddy的数量

文件结构

源代码

abnormal.s        

start.s        

init.s

types.h

boot.c

mmu.c

printk.c

string.h

string.c

interrupt.c

memory.c

链接脚本

leeos.lds

编译脚本

makefile

仿真软件脚本

skyeye.conf

文件详情

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:
	nop
__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

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

#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();
	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();
}

链接脚本

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

.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
#io
mem_bank: map = I, type = RW, addr = 0x48000000, size = 0x20000000

运行效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值