基本思路:
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