⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 malloc.c

📁 一款MP3 Player Firmware 的原代码,非常有参考价值
💻 C
字号:
#include "malloc.h"#include "as31glue.h"#include "printf.h"#include <8051.h>/* this "simm_id" type is what will normally be passed around, *//* and declared inside of other structs (like playlists, file *//* lists, etc.  You can't actually access memory with it until *//* you pass it through a function to turn it into a proper C *//* xdata pointer (see below) *///  defined in malloc.h// typedef unsigned long  simm_id;/* Normally this complex union won't be used *//* This funny union represents a block/offset memory address *//* and allows it to be passed between functions as a 32 bit *//* long, because SDCC can't pass structs or unions. */// typedef union dram_memory_pointer_struct {typedef union {	struct {		unsigned int offset;		unsigned int block;	} part;	simm_id addr32;} simm_id_union;#define DATA_PER_BLOCK 4090struct simm_block_struct {	unsigned int free_bytes;	unsigned int ref_count;	unsigned int next;	unsigned char bytes[DATA_PER_BLOCK];};static xdata unsigned int first_malloced_block;static xdata unsigned int last_malloced_block;/* don't try this sort of direct hardware access at home! */volatile static xdata at 0xFF0E unsigned int block7000;static xdata at 0x7000 struct simm_block_struct p7;#define DRAM_PAGE_CFG 0xFF00void init_malloc(void){	block7000 = first_malloced_block = \	   last_malloced_block = malloc_blocks(1);	//printf("malloc 1st: %d\r\n", block7000);	p7.next = 0;	p7.free_bytes = DATA_PER_BLOCK;	p7.ref_count = 0;}#define USE_ASM_MALLOC#ifndef USE_ASM_MALLOCsimm_id simm_malloc(unsigned int num_bytes){	unsigned int block;	xdata simm_id_union mem;	unsigned int block7000_save;	// printf("simm_malloc begin, f=%d\r\n", first_malloced_block);	if (num_bytes > DATA_PER_BLOCK) return 0;	//P1_3 = 1;	block7000_save = block7000;	block7000 = last_malloced_block;	if (p7.free_bytes < num_bytes) {		block = malloc_blocks(1);		//printf("malloc Nth: %d\r\n", block7000);		p7.next = last_malloced_block = block;		block7000 = block;		p7.next = 0;		p7.free_bytes = DATA_PER_BLOCK;		p7.ref_count = 0;	}	mem.part.offset = 4096 - p7.free_bytes;	p7.free_bytes -= num_bytes;	p7.ref_count++;	//printf("malloc: %d bytes, returning %lx\r\n", num_bytes, mem.addr32);	mem.part.block = block7000;	block7000 = block7000_save;	//P1_3 = 0;	return mem.addr32;}#endif#ifdef USE_ASM_MALLOC#pragma SAVE#pragma LESS_PEDANTICsimm_id simm_malloc(unsigned int num_bytes){	num_bytes; // passed in dptr	_asm	// if (num_bytes > DATA_PER_BLOCK) return 0;	mov	a, #(65535 - DATA_PER_BLOCK) & 255	add	a, dpl	mov	a, #(65535 - DATA_PER_BLOCK) >> 8	addc	a, dph	jnc	00001$	clr	a		// return 0	mov	dpl, a	mov	dph, a	mov	b, a	ret00001$:	mov	r2, dpl		// put num_bytes into r3/r2	mov	r3, dph	mov	dptr, #_last_malloced_block	movx	a, @dptr	mov	r4, a		// fetch last_malloced_block into r5/r4	inc	dptr	movx	a, @dptr	mov	r5, a	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	movx	a, @dptr	push	acc		// save caller's addr7 onto stack	mov	a, r4	movx	@dptr, a	// and map last_malloced_block @ 7000	inc	dptr	movx	a, @dptr	push	acc	mov	a, r5	movx	@dptr, a	mov	dptr, #0x7000 + 0	movx	a, @dptr	// read p7.free_bytes into r7/r6	mov	r6, a	clr	c	subb	a, r2		// and compare with num_bytes	mov	r0, a		// and keep result in r1/r0	inc	dptr	movx	a, @dptr	mov	r7, a	subb	a, r3	mov	r1, a	jnc	00002$		// skip if num_bytes <= p7.free_bytes	// get another block from drivers.asm and link it into list	// this part is not as speed critical, since the normal activity	// is packing more stuff into already allocated blocks.	push	ar2	push	ar3	mov	dpl, #1	lcall	_malloc_blocks	mov	r4, dpl		// store block in r5/r4	mov	r5, dph	pop	ar3	pop	ar2	mov	dptr, #_last_malloced_block	mov	a, r4	movx	@dptr, a	// last_malloced_block = block	inc	dptr	mov	a, r5	movx	@dptr, a	mov	dptr, #0x7000 + 4	mov	a, r4	movx	@dptr, a	// p7.next = block	inc	dptr	mov	a, r5	movx	@dptr, a	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	mov	a, r4	movx	@dptr, a	// block7000 = block (map new blk at 7000)	inc	dptr	mov	a, r5	movx	@dptr, a	mov	dptr, #0x7000 + 2	clr	a	movx	@dptr, a	// p7.ref_count = 0	inc	dptr	movx	@dptr, a	inc	dptr	movx	@dptr, a	// p7.next = 0	inc	dptr	movx	@dptr, a	// need to compute r7/r6 and r1/r0 (used below), based on r3/r2	clr	c	mov	a, #DATA_PER_BLOCK & 255	mov	r6, a		// r7/r6 = DATA_PER_BLOCK	subb	a, r2	mov	r0, a		// r1/r0 = DATA_PER_BLOCK - num_bytes	mov	a, #DATA_PER_BLOCK >> 8	mov	r7, a	subb	a, r3	mov	r1, a	// end of code within if (p7.free_bytes < num_bytes) ...00002$:	mov	dptr, #0x7000 + 0	mov	a, r0	movx	@dptr, a	// store p7.free_bytes -= num_bytes	inc	dptr	mov	a, r1	movx	@dptr, a	mov	dptr, #0x7000 + 2	movx	a, @dptr	add	a, #1		// increment p7.ref_count	movx	@dptr, a	inc	dptr	movx	a, @dptr	addc	a, #0	movx	@dptr, a	mov	dptr, #DRAM_PAGE_CFG + (7 * 2) + 1	pop	acc	movx	@dptr, a	// restore caller's addr7 mapping	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	pop	acc	movx	@dptr, a	clr	c	clr	a	subb	a, r6		// compute 4096 - p7.free_bytes	mov	dpl, a		// and return it as mem.offset	mov	a, #16	subb	a, r7	mov	dph, a	mov	b, r4		// return block number as mem.block	mov	a, r5	_endasm;}#pragma RESTORE#endifvoid simm_free(simm_id addr32){	unsigned int block, next_block;	xdata simm_id_union mem;	unsigned int block7000_save;	block7000_save = block7000;	mem.addr32 = addr32;	block7000 = mem.part.block;	if (--(p7.ref_count) != 0) return;	if (mem.part.block == first_malloced_block) {		first_malloced_block = p7.next;		free_blocks(mem.part.block);		block7000 = block7000_save;		return;	}	next_block = p7.next;	free_blocks(mem.part.block);	for (block = first_malloced_block; block != 0; block = p7.next) {		block7000 = block;		if (p7.next == mem.part.block) {			p7.next = next_block;			if (next_block == 0) {				last_malloced_block = block;			}			block7000 = block7000_save;			return;		}	}	block7000 = block7000_save;	print("Error: could find freed block\r\n");}volatile xdata at 0xFF0A unsigned int addr5_val;volatile xdata at 0xFF0C unsigned int addr6_val;volatile xdata at 0xFF0E unsigned int addr7_val;#pragma LESS_PEDANTIC/* This is the magic function that takes the "pointer" type *//* from malloc and maps the referenced block into the 8051's *//* address space and returns a SDCC xdata * to the memory *//* See http://www.pjrc.com/tech/mp3/mem_map.html for more *//* details about how the DRAM controller page allocation works */xdata void * addr5(simm_id addr32){	addr32;	 /* suppress unused variable warning */	_asm	push	dph		;save offset on stack	push	dpl	xch	a, b		;keep msb of block in b	mov	dptr, #DRAM_PAGE_CFG + (5 * 2)	;always map in 5000-5FFF	movx	@dptr, a	inc	dptr	mov	a, b	movx	@dptr, a	;map the block to 0x5000	pop	dpl	pop	acc	anl	a, #15	add	a, #0x50	mov	dph, a		;now dptr points to the users data	_endasm;}xdata void * addr6(simm_id addr32){	addr32;	 /* suppress unused variable warning */	_asm	push	dph		;save offset on stack	push	dpl	xch	a, b		;keep msb of block in b	mov	dptr, #DRAM_PAGE_CFG + (6 * 2)	;always map in 6000-6FFF	movx	@dptr, a	inc	dptr	mov	a, b	movx	@dptr, a	;map the block to 0x6000	pop	dpl	pop	acc	anl	a, #15	add	a, #0x60	mov	dph, a		;now dptr points to the users data	_endasm;}xdata void * addr7(simm_id addr32){	addr32;	 /* suppress unused variable warning */	_asm	push	dph		;save offset on stack	push	dpl	xch	a, b		;keep msb of block in b	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	;always map in 7000-7FFF	movx	@dptr, a	inc	dptr	mov	a, b	movx	@dptr, a	;map the block to 0x7000	pop	dpl	pop	acc	anl	a, #15	add	a, #0x70	mov	dph, a		;now dptr points to the users data	_endasm;}// calling addr6(variable) is the same as addr6p(&variable)// except that addr6p does the 32 bit fetch from xdata much// more efficiently than the compiler-generated code can,// and it saves a lot of code space.  A preprocessor macro// called Addr6() allows you to use addr6p more easily by// just changing the 'a' to 'A'.xdata void * addr6p(xdata simm_id * xaddr16){	xaddr16;	_asm	movx	a, @dptr	;fetch offset lsb	inc	dptr	push	acc		;keep addr lsb on stack	movx	a, @dptr	;fetch offset msb	inc	dptr	anl	a, #15	add	a, #0x60	push	acc	movx	a, @dptr	;fetch block lsb	inc	dptr	mov	b, a	movx	a, @dptr	;fetch block msb	mov	dptr, #DRAM_PAGE_CFG + (6 * 2) + 1	;always map in 6000-6FFF	movx	@dptr, a	mov	a, b	mov	dptr, #DRAM_PAGE_CFG + (6 * 2)	movx	@dptr, a	pop	dph	pop	dpl	_endasm;}#define USE_GOOD_ADDR7xdata void * addr7p(xdata simm_id * xaddr16){	xaddr16;#ifdef USE_GOOD_ADDR7	_asm	movx	a, @dptr	;fetch offset lsb	inc	dptr	push	acc		;keep addr lsb on stack	movx	a, @dptr	;fetch offset msb	inc	dptr	anl	a, #15	add	a, #0x70	push	acc	movx	a, @dptr	;fetch block lsb	inc	dptr	mov	b, a	movx	a, @dptr	;fetch block msb	mov	dptr, #DRAM_PAGE_CFG + (7 * 2) + 1	;always map in 7000-7FFF	movx	@dptr, a	mov	a, b	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	movx	@dptr, a	pop	dph	pop	dpl	_endasm;#else	// Why does this code not work???  Is there some strange	// issue with using dual-dptr that I do not understand???	_asm	movx	a, @dptr	;fetch offset lsb	inc	dptr	push	acc		;keep addr lsb on stack	movx	a, @dptr	;fetch offset msb	inc	dptr	anl	a, #15	add	a, #0x70	mov	b, a		;keep addr msb in b	movx	a, @dptr	;fetch block lsb	inc	dptr	inc	AUXR1	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	;always map in 7000-7FFF	movx	@dptr, a	inc	dptr	inc	AUXR1	movx	a, @dptr	;fetch block msb	inc	AUXR1	movx	@dptr, a	inc	AUXR1	mov	dph, b	pop	dpl	_endasm;#if 0	// This also does not work.  Maybe there's some bug in the FPGA where	// the write to the msb of the dram page mapping registers is messed	// up by the previous read??	_asm	movx	a, @dptr	;fetch offset lsb	inc	dptr	push	acc		;keep addr lsb on stack	movx	a, @dptr	;fetch offset msb	inc	dptr	anl	a, #15	add	a, #0x70	mov	b, a		;keep addr msb in b	movx	a, @dptr	;fetch block lsb	inc	dptr	push	dpl	push	dph	mov	dptr, #DRAM_PAGE_CFG + (7 * 2)	;always map in 7000-7FFF	movx	@dptr, a	pop	dph	pop	dpl	movx	a, @dptr	;fetch block msb	mov	dptr, #DRAM_PAGE_CFG + (7 * 2) + 1	movx	@dptr, a	mov	dph, b	pop	dpl	_endasm;#endif#endif}/* this function does the opposite of the addrX functions. *//* if you have a pointer to dynamically allocated memory, *//* (which is currently mapped into the processor's address *//* space, you can pass that 16 bit pointer to this function *//* and get the full 32 bit simm_id that represents where *//* that memory is within the SIMM */simm_id simm_id_from_pointer(xdata void *ptr){	ptr;	_asm	push	dpl		;save the pointer, we need it later	push	dph	mov	a, dph	swap	a	anl	a, #15		;acc has page # where mapped	rl	a	mov	dpl, a		;(LSB of DRAM_PAGE_CFG assumed to be zero)	mov	dph, #DRAM_PAGE_CFG >> 8	movx	a, @dptr	;read LSB of mapped block number	inc	dptr	mov	b, a	movx	a, @dptr	;read MSB of mapped block number	pop	dph	anl	dph, #15	;offset is lower 12 bits of the pointer	pop	dpl	_endasm;}// TODO: test these push/pop functions... do they really work?#define AUXR1 0xA2void push_addr(unsigned char num){	num;	_asm	inc	AUXR1	pop	dph	pop	dpl	inc	AUXR1	mov	a, dpl	rl	a	mov	dpl, a	mov	dph, #DRAM_PAGE_CFG >> 8	movx	a, @dptr	push	acc	inc	dptr	movx	a, @dptr	push	acc	inc	AUXR1	clr	a	jmp	@a+dptr	_endasm;}void pop_addr(unsigned char num){	num;	_asm	inc	AUXR1	pop	dph	pop	dpl	inc	AUXR1	mov	a, dpl	rl	a	mov	dpl, a	mov	dph, #DRAM_PAGE_CFG >> 8	pop	b	pop	acc	movx	@dptr, a	inc	dptr	mov	a, b	movx	@dptr, a	inc	AUXR1	clr	a	jmp	@a+dptr	_endasm;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -