// ***************** overlay.c *************************************** // Risc-Dsp runtime library // // This file implements interface to dsp overlays handling // // (c) multicore.ru // // ******************************************************************* #include #include #include "libdsp.h" #include "mcom02.h" #include "overlay.h" // // address of dsp-runtime finction exit() // it must be implemented in dsp code // extern int __dsp_exit; // // working overlays // struct ovl_dsp_ctx dsp_ctx[MAX_DSP]; extern void __overlay_ctx_init_table(struct ovl_ctx * ctx); // variables for overlays handling unsigned curr_dsp_num = 0xffffffff; static unsigned ctx_is_init = 0; // // @name: init_dsp_entry // @description: initializaion of dsp entries // void init_dsp_entry() { memset(dsp_ctx,0,sizeof(struct ovl_dsp_ctx)*MAX_DSP); int i,j; for(i = 0; i < MAX_DSP; i++) { for(j = 0; j < MAX_OVERLAY_CTX; j++) { dsp_ctx[i].ctx[j].dsp_info = &dsp_ctx[i].info; dsp_ctx[i].ctx[j].__num = j; } dsp_ctx[i].curr_ctx_num = 0xffffffff; } ctx_is_init = 1; } // // @name: set_curr_dsp // @description: switch working dsp // // @in unsigned num - dsp num (0..3) // void set_curr_dsp(unsigned num) { curr_dsp_num = num; } // // @name: calc_pram_size // @description: calculates size of pram according to given page mode // // @in unsigned page_mode - dsp num (0..3) // @return - size !=0 if page mode is corect // 0 - error page mode unsigned calc_pram_size(unsigned page_mode) { unsigned memory_size = 0; switch(page_mode) { case 0 : memory_size = 0x8000; break; case 2 : memory_size = 0x8000*3; break; case 3 : memory_size = 0x8000*4; break; default: break; } return memory_size; } // // @name: calc_xyram_size // @description: calculates size of xram according to given page mode // // @in unsigned page_mode - dsp num (0..3) // @return - size !=0 if page mode is corect // 0 - error page mode // unsigned calc_xyram_size(unsigned page_mode) { unsigned memory_size = 0; switch(page_mode) { case 0 : memory_size = 0x8000*4; break; case 2 : memory_size = 0x8000*2; break; case 3 : memory_size = 0x8000; break; default: break; } return memory_size; } // // @name: calc_xyram_size // @description: calculates size of xram according to given page mode // // @in unsigned page_mode - dsp num (0..3) // @return - size !=0 if page mode is corect // 0 - error page mode // void add_dsp_entry( unsigned num, unsigned page_mode, unsigned qstr_stop, unsigned pram_base, unsigned xyram_base) { if(!ctx_is_init) init_dsp_entry(); if(num >= MAX_DSP) return; dsp_ctx[num].info.num = num; dsp_ctx[num].info.page_mode = page_mode; dsp_ctx[num].info.qstr_stop = qstr_stop; dsp_ctx[num].info.pram_base = pram_base; dsp_ctx[num].info.pram_size = calc_pram_size(page_mode); dsp_ctx[num].info.xyram_base = xyram_base; dsp_ctx[num].info.xyram_size = calc_xyram_size(page_mode); dsp_ctx[num].info.__present = 1; } // // @name: config_overlay // @description: init dsp description entries, set page mode, setup overlay config // // @in unsigned num - dsp num (0..3) // @in unsigned page_mode - (0,2,3) - sets ratio between pram:xram memory size // void config_overlay(unsigned num, unsigned page_mode) { init_dsp_entry(); add_dsp_entry(0x0, page_mode, 0x3, 0x3a600000, 0x3a400000); // dsp0 entry add_dsp_entry(0x1, page_mode, 0xB, 0x3a620000, 0x3a420000); // dsp1 entry print_dsp_memory_info(); common_regs* dsp_common = (common_regs*)(_REGSCM); dsp_common->CSR |= ((page_mode << 2) & 0xC); init_overlay(num); // init overlay for DSP set_curr_dsp(num); } // // @name: find_overlay_ctx // @description: select overlay at given address // // @in unsigned address - address of program // @return - struct ovl_ctx* != NULL - overlay section // NULL - address is not valid or overlay for given address was not created // struct ovl_ctx* find_overlay_ctx(unsigned address) { struct ovl_ctx* find_ctx = 0; struct ovl_ctx* curr_ctx = 0; if(curr_dsp_num >= MAX_DSP) return 0; struct ovl_dsp_ctx * curr_dsp_ctx = &dsp_ctx[curr_dsp_num]; int i; for(i = 0; i < MAX_OVERLAY_CTX; i++) { curr_ctx = &curr_dsp_ctx->ctx[i]; if(!curr_ctx->__present) break; // end of ctx table unsigned bottom = *((int*)&curr_ctx->__text_src); unsigned top = bottom + curr_ctx->__text_size; unsigned bottom_data = *((int*)&curr_ctx->__data_src); unsigned top_data = bottom_data + curr_ctx->__data_size; if((address >= bottom && address < top) || (address >= bottom_data && address < top_data)) { find_ctx = curr_ctx; break; } } return find_ctx; } // // @name: init_overlay // @description: select active overlay and load it into memory // // @in unsigned num - core id [0..MAX_DSP] // void init_overlay(unsigned num) { if(num >= MAX_DSP) // num overflow MAX_DSP number { return; } if(!dsp_ctx[num].info.__present) { return; } // set overlay table curr_dsp_num = num; struct ovl_dsp_ctx * curr_dsp_ctx = &dsp_ctx[curr_dsp_num]; __overlay_ctx_init_table(curr_dsp_ctx->ctx); /* unsigned exit_address = (unsigned)curr_dsp_ctx->ctx[curr_dsp_ctx->curr_ctx_num].__exit_address; unsigned __dsp_exit_address; struct ovl_ctx* find_ctx = find_overlay_ctx(exit_address); if(find_ctx) { __dsp_exit_address = (exit_address - (unsigned int)find_ctx->__text_src)>>2; } else { return; } */ int i; for(i = 0; i < MAX_OVERLAY_CTX; i++) { if(!curr_dsp_ctx->ctx[i].__present) break; // end of ctx table unsigned exit_address = (unsigned)curr_dsp_ctx->ctx[i].__exit_address; unsigned __dsp_exit_address = (exit_address - (unsigned int)curr_dsp_ctx->ctx[i].__text_src)>>2; curr_dsp_ctx->ctx[i].__exit_dsp = __dsp_exit_address; } print_overlay(curr_dsp_ctx->ctx); // load_overlay(find_ctx); } // // @name: load_overlay // @description: load overlay it into memory // // @in struct ovl_ctx* ctx - ovrelay to be loaded // @return 1 - overlay is loaded // 0 - memory boundary error // int load_overlay(struct ovl_ctx* ctx) { // check need load if(ctx->__num == dsp_ctx[curr_dsp_num].curr_ctx_num && ctx->dsp_info->num == curr_dsp_num) { return 1; // already loaded } unsigned *src, *dst; unsigned size; // load program src = ctx->__text_src; dst = ctx->__text_dst; size = (ctx->__text_size + 3) & 0xfffffffc; // verify address if(((unsigned)(dst) >= ctx->dsp_info->pram_base) && (((unsigned)(dst) + size) <= (ctx->dsp_info->pram_base + ctx->dsp_info->pram_size))) { if(src != dst) while(size) *dst++ = *src++,size-=4; } else { asm("sizepramerror: .globl sizepramerror"); return 0; } src = ctx->__data_src; dst = ctx->__data_dst; size = (ctx->__data_size + 3) & 0xfffffffc; // verify address if(((unsigned)(dst) >= ctx->dsp_info->xyram_base) && (((unsigned)(dst) + size) <= (ctx->dsp_info->xyram_base + ctx->dsp_info->xyram_size))) { if(src != dst) while(size) *dst++ = *src++,size-=4; } else { asm("sizexramerror: .globl sizexramerror"); return 0; } src = ctx->__bss_src; dst = ctx->__bss_dst; size = (ctx->__bss_size + 3) & 0xfffffffc; // verify address if(((unsigned)(dst) >= ctx->dsp_info->xyram_base) && (((unsigned)(dst) + size) <= (ctx->dsp_info->xyram_base + ctx->dsp_info->xyram_size))) { if(src != dst) while(size) *dst++ = *src++,size-=4; } else { return 0; } dsp_ctx[curr_dsp_num].curr_ctx_num = ctx->__num; return 1; } // @name: print_overlay // @description: reports overlay content, (uncomment code in source to use it) // // @in struct ovl_ctx* ctx - ovrelay to be reported // void print_overlay(struct ovl_ctx* ctx) { //debug_printf("overlay_info: \n"); //debug_printf("text : %08x -> %08x, (0x%x) \n", ctx->__text_src, ctx->__text_dst, ctx->__text_size); //debug_printf("data : %08x -> %08x, (0x%x) \n", ctx->__data_src, ctx->__data_dst, ctx->__data_size); //debug_printf("bss : %08x -> %08x, (0x%x) \n", ctx->__bss_src, ctx->__bss_dst, ctx->__bss_size); } // @name: print_dsp_memory_info // @description: reports dsp_memory settings (uncomment code in source to use it) // void print_dsp_memory_info() { int i; //debug_printf("dsp memory info: \n"); for(i = 0; i < MAX_DSP; i++) { if(!dsp_ctx[i].info.__present) break; //debug_printf("dsp[%d] pram - [%08x : %08x], (0x%05x)\n",i, dsp_ctx[i].info.pram_base, //dsp_ctx[i].info.pram_base + dsp_ctx[i].info.pram_size, dsp_ctx[i].info.pram_size); //debug_printf("dsp[%d] xyram - [%08x : %08x], (0x%05x)\n",i, dsp_ctx[i].info.xyram_base, //dsp_ctx[i].info.xyram_base + dsp_ctx[i].info.xyram_size, dsp_ctx[i].info.xyram_size); } } // @name: xyram_byte_address_to_risc // @description: converts address from dsp byte address space into risc address space // @inputs: address - address value in dsp byte address space // page_size - // @return: address value in risc address space unsigned xyram_byte_address_to_risc(unsigned address, unsigned page_size) { address += ((unsigned)address >= page_size)? ((unsigned int)_XYRAM1 - page_size) : (unsigned int)_XYRAM0; return address; } // @name: xyram_word_address_to_risc // @description: converts address from dsp byte address space into risc address space // @inputs: address - address value in dsp word address space // page_size - // @return: address value in risc address space unsigned xyram_word_address_to_risc(unsigned address, unsigned page_size) { unsigned address_rebase = ((unsigned)(address << 2) >= page_size)? ((unsigned int)_XYRAM1 - page_size) : _XYRAM0; address = address_rebase + (address << 2); return address; } // @name: risc_to_xyram_byte_address // @description: converts address from risc address space into dsp byte address space // @inputs: address - address value in dsp byte address space // page_size - // @return: address value in risc address space unsigned risc_to_xyram_byte_address(unsigned address, unsigned page_size) { unsigned address_rebase = (unsigned int)_XYRAM0; address -= address_rebase; return address; } // @name: risc_to_xyram_word_address // @description: converts address from risc address space into dsp word address space // @inputs: address - address value in dsp byte address space // page_size - // @return: address value in risc address space unsigned risc_to_xyram_word_address(unsigned address, unsigned page_size) { unsigned address_rebase = (unsigned int)_XYRAM0; address -= address_rebase; return address>>2; } // @name: get_page_size // @description: gets size of memory page accordingly to page_mode // @inputs: page_mode unsigned get_page_size(unsigned page_mode) { unsigned page_size = 0; switch(page_mode){ case 0 : page_size = 0x8000*4; break; case 2 : page_size = 0x8000*2; break; case 3 : page_size = 0x8000; break; default: ; } return page_size; }