📄 malloc.c
字号:
#include "malloc.h"#include "as31glue.h"#include "printf.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 next; unsigned int free_bytes; unsigned int ref_count; unsigned char bytes[DATA_PER_BLOCK];};static data unsigned int first_malloced_block=0;static data 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;simm_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; block7000_save = block7000; if (first_malloced_block == 0) { 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; } else { 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.block = block7000; 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); block7000 = block7000_save; return mem.addr32;}void 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;/* 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 */#define DRAM_PAGE_CFG 0xFF00xdata 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;}/* 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -