首页
开源
资讯
活动
开源许可证
软件工程云服务
软件代码质量检测云服务
持续集成与部署云服务
社区个性化内容推荐服务
贡献审阅人推荐服务
群体化学习服务
重睛鸟代码扫描工具
登录
注册
代码拉取完成,页面将自动刷新
Watch
26
Star
74
Fork
32
珠海杰理科技
/
fw-AD15N
Fork 仓库
加载中
取消
确认
代码
Issues
204
Pull Requests
0
Wiki
2
统计
更新失败,请稍后重试!
Issues
/
详情
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
FAQ:AD17N同时播放F1A和A会失败异常?保留MIDI+A同时工作,也可以实现F1A+A同时播放的方法
待办的
#IAH8O0
Lj-job
成员
创建于
2024-08-01 17:52
### 一、简介 AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。 1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的; 2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源 **注1:实现后,提高系统时钟以面对更大的运行压力。** **注2: 此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。 AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别: AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间; AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间; 上面两个版本在申请时,大小是有所区别的;** **注3: 本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)** **注4: 如果要自行修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。** ### 二、方法 1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c) 2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c) 3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c) ### 三、具体实现 1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c) ![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图") ![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图") 2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c) ![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图") 3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c) ![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图") ### 相关源代码: **1、app\bsp\common\decoder\list\f1a_api.c:** ``` #include "f1a_api.h" #include "cpu.h" #include "config.h" #include "typedef.h" //#include "hwi.h" #include "decoder_api.h" //#include "dev_manage.h" #include "vfs.h" //#include "fs.h" #include "circular_buf.h" #include "dac.h" /* #include "resample.h" */ /* #include "speed_api.h" */ #include "msg.h" #include "errno-base.h" #include "decoder_msg_tab.h" #include "app_config.h" #include "decoder_cpu.h" #include "app_modules.h" //#include "avio.h" //#include "bitstream.h" //#include "wmadata.h" #if defined(DECODER_F1A_EN) && (DECODER_F1A_EN) #define LOG_TAG_CONST NORM #define LOG_TAG "[normal]" #include "log.h" bool f1a_type_run; #define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE) #define F1A_DBUF_SIZE (0xc64) #define F1A_OUTPUT_MAX_SIZE (32 * 2) #define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2)) dec_obj dec_f1a_hld[MAX_F1A_CHANNEL]; #if HAS_F1A_MASK_TAB const int cos_tab_split = 1300 / 4; /* const int f1a_cos_maskrom_tab[1] = {0}; */ #else const int cos_tab_split = 0; const int f1a_cos_maskrom_tab[1] = {0}; #endif /*************************************************************/ /* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */ /* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */ /* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */ typedef struct _f1x_data { cbuffer_t cbuf; u16 o_buf[F1A_OBUF_SIZE / 2]; u16 d_buff[F1A_DBUF_SIZE / 2]; } f1x_data; f1x_data g_f1x1_data AT(.f1a_1_buf); f1x_data g_f1x2_data AT(.f1a_2_buf); const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = { { &dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL mp_input, mp_output, }, #if (MAX_F1A_CHANNEL > 1) { &dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL mp_input, mp_output, } #endif }; const char f1a_ext[] = {".f1a"}; const char f1b_ext[] = {".f1b"}; const char f1c_ext[] = {".f1c"}; const char f1x_ext[] = {".f1x"}; extern audio_decoder_ops *get_f1a_ops(); u8 g_loop_tab[10] = { 0, 1, 2, 0, 0, 1, 2, 3, 2, 1 }; u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data) { u32 buff_len, i; decoder_ops_t *ops; /* void *name; */ /* char name[16] = {0}; */ char ctype = 0; log_info("f1a_decode_api"); void *p_cbuf; dec_obj *p_dec_hld; void *p_obuf; void *p_dbuf; void *p_dec_io; if (index >= MAX_F1A_CHANNEL) { return E_F1A_INDEX; } /* p_cbuf = &cbuf_f1a[index]; */ /* p_obuf = &obuf_f1a[index][0]; */ /* p_dbuf = &f1a_decode_buff[index][0]; */ p_cbuf = &p_f1x_data->cbuf; p_obuf = &p_f1x_data->o_buf[0]; p_dbuf = &p_f1x_data->d_buff[0]; p_dec_hld = &dec_f1a_hld[index]; p_dec_io = (void *)&f1a_dec_io[index]; local_irq_disable(); memset(p_dec_hld, 0, sizeof(dec_obj)); local_irq_enable(); dec_f1a_hld[0].type = D_TYPE_F1A_1; #if (MAX_F1A_CHANNEL > 1) dec_f1a_hld[1].type = D_TYPE_F1A_2; #endif ops = get_f1a_ops(); buff_len = ops->need_dcbuf_size(); if (buff_len > F1A_DBUF_SIZE) { log_info("f1a buff need : 0x%x\n", buff_len); return E_F1A_DBUF; } /******************************************/ cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE); /* log_info("A\n"); */ /* log_info("c buffrt 0x%x\n",p_cbuf); */ /* log_info("B\n"); */ p_dec_hld->p_file = p_file; p_dec_hld->sound.p_obuf = p_cbuf; p_dec_hld->sound.para = F1A_KICK_SIZE; p_dec_hld->p_dbuf = p_dbuf; p_dec_hld->dec_ops = ops; p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0]; p_dec_hld->p_dp_buf = p_dp_buf; /* log_info("C\n"); */ // /******************************************/ /* name = vfs_file_name(p_file); */ int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname)); log_info("file name : %s", g_file_sname); u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下 if (check_ext_api(g_file_sname, f1a_ext, 4)) { ctype = 'a'; } else if (check_ext_api(g_file_sname, f1b_ext, 4)) { ctype = 'b'; } else if (check_ext_api(g_file_sname, f1c_ext, 4)) { ctype = 'c'; if (ops->format_check(p_dbuf)) { //格式检查 log_error("f1c format err\n"); return E_F1A_FORMAT; } } else if (check_ext_api(g_file_sname, f1x_ext, 4)) { ctype = 'x'; void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par); if (NULL == pf1x) { log_error("f1x null\n"); return E_F1X_FORMAT; } ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x); if (ops->format_check(p_dbuf)) { //格式检查 log_error("f1x format err\n"); return E_F1A_FORMAT; } } else { log_error("f1a type err\n"); return E_F1A_TYPE; } log_info("file is a f1%c", ctype); regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC; /*************************************************/ /* log_info("E\n"); */ if ('b' == ctype) { i = 32000; } else { i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率 } log_info("file sr : %d\n", i); /* dac_sr_api(i); */ p_dec_hld->sr = i; *p_dec = p_dec_hld; f1a_type_run = 1; return 0; /* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */ /* kick_decoder(); */ /* return 0; */ } //-------------------------------- u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf) { return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data); } u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf) { #if (MAX_F1A_CHANNEL > 1) return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data); #else return E_F1A_OUTRGE; #endif } /* extern const u8 _buf_start[]; */ /* extern const u8 _buf_end[]; */ extern const u8 f1a_1_buf_start[]; extern const u8 f1a_1_buf_end[]; extern const u8 f1a_2_buf_start[]; extern const u8 f1a_2_buf_end[]; u32 f1a_1_buff_api(dec_buf *p_dec_buf) { p_dec_buf->start = (u32)&f1a_1_buf_start[0]; p_dec_buf->end = (u32)&f1a_1_buf_end[0]; return 0; } u32 f1a_2_buff_api(dec_buf *p_dec_buf) { p_dec_buf->start = (u32)&f1a_2_buf_start[0]; p_dec_buf->end = (u32)&f1a_2_buf_end[0]; return 0; } #endif ``` **2、app\bsp\lib\my_malloc.c:** ``` #include "my_malloc.h" /* #define LOG_TAG_CONST HEAP */ #define LOG_TAG_CONST NORM #define LOG_TAG "[malloc]" #include "log.h" /* void *pvPortMalloc( size_t xWantedSize ) */ /* u32 example(u32 dat) */ /* { */ /* if (dat & 0x80) { */ /* dat += 1; */ /* } else { */ /* dat <<= 1; */ /* } */ /* return dat; */ /* } */ const u16 configHEAP_BEST_SIZE = 100; extern bool f1a_type_run; u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf); u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf); void *my_malloc(u32 size, mm_type xType) { void *res; /* return pvPortMalloc(size); */ if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间 log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size); memset(spec_src_tmp_buf1, 0, size); return spec_src_tmp_buf1; } if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) { f1a_type_run = 0; memset(spec_src_tmp_buf2, 0, size); log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size); return spec_src_tmp_buf2; } res = pvPortMalloc(size, xType); if (NULL != res) { log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType); memset(res, 0, size); } else { log_info(" err malloc empty\n"); } return res; } void *my_free(void *pv) { if (pv == spec_src_tmp_buf1) { memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1)); log_info("spec src free!\n"); return NULL; } if (pv == spec_src_tmp_buf2) { memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2)); log_info("spec src free!\n"); return NULL; } if (NULL != pv) { vPortFree(pv); } return NULL; } extern const u8 _free_start[]; extern const u8 _free_end[]; void my_malloc_init(void) { u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1; log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]); memset((void *)&_free_start[0], 0, len); vPortInit((void *)&_free_start[0], len); } void xTaskResumeAll(void) { ; } ``` **3、app\post_build\sh57\voice_toy\app_ld.c:** ``` // *INDENT-OFF* #include "maskrom_stubs.ld" //config _BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24; MEMORY { app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100 ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000 boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24 } ENTRY(_start) SECTIONS { /* L1 memory sections */ . = ORIGIN(boot_ram); .boot_data ALIGN(4): { *(.boot_info) } > boot_ram . = ORIGIN(ram0); .data ALIGN(4): { PROVIDE(data_buf_start = .); *(.data*) *(.*.data) cache_Lx_code_text_begin = .; *(.common) /* *(.ram_code) */ /* *(.volatile_ram_code) */ *(.*.text.cache.L1) *(.*.text.cache.L2) *(.*.text.cache.L3) . = (. + 3) / 4 * 4 ; cache_Lx_code_text_end = .; } > ram0 .debug_data ALIGN(4): { PROVIDE(debug_buf_start = .); *(.debug_bss) *(.debug_data) } > ram0 .bss (NOLOAD) : SUBALIGN(4) { PROVIDE(bss_buf_start = .); . = ALIGN(4); _cpu0_sstack_begin = .; . = ALIGN(4); *(.intr_stack) . = ALIGN(4); *(.stack_magic); . = ALIGN(4); *(.stack) . = ALIGN(4); *(.stack_magic0); . = ALIGN(4); _cpu0_sstack_end = .; . = ALIGN(4); _system_data_begin = .; *(.bss) *(.*.data.bss) *(.non_volatile_ram) . = ALIGN(4); _system_data_end = .; *(.DAC_BUFFER) *(.AUDIO_ADC_BUFFER) } > ram0 /* OVERLAY : */ .effect_buf ALIGN(4): { PROVIDE(effect_buf_start = .); . = ALIGN(4); *(.sp_data) . = ALIGN(4); *(.rs_data) /* .d_sp { *(.sp_data) } */ /* .d_rs { *(.rs_data) } */ } > ram0 /* _ram0_end = .; */ .dec_buf ALIGN(4): { PROVIDE(a_buf_start = .); *(.a_data); PROVIDE(a_buf_end = .); } > ram0 _overlay_start = .; /* . = ORIGIN(ram1); */ OVERLAY : AT(0x200000) { .d_spec_src { PROVIDE(spec_src_buf_start = .); *(.spec_src_buf); PROVIDE(spec_src_buf_end = .); } .d_midi_ctrl { PROVIDE(midi_ctrl_buf_start = .); *(.midi_ctrl_buf); PROVIDE(midi_ctrl_buf_end = .); } .d_midi { PROVIDE(midi_buf_start = .); *(.midi_buf); PROVIDE(midi_buf_end = .); } .d_toy_music { . = spec_src_buf_end; PROVIDE(toy_music_buf_start = .); *(.toy_music_data); PROVIDE(toy_music_buf_end = .); } .d_ump3 { . = toy_music_buf_end; PROVIDE(ump3_buf_start = .); *(.ump3_data); PROVIDE(ump3_buf_end = .); } .d_mp3_st { . = toy_music_buf_end; PROVIDE(mp3_st_buf_start = .); *(.mp3_st_data); PROVIDE(mp3_st_buf_end = .); } .d_wav { . = toy_music_buf_end; PROVIDE(wav_buf_start = .); *(.wav_data); PROVIDE(wav_buf_end = .); } .d_f1a { . = toy_music_buf_end; PROVIDE(f1a_1_buf_start = .); *(.f1a_1_buf); PROVIDE(f1a_1_buf_end = .); PROVIDE(f1a_2_buf_start = .); *(.f1a_2_buf); PROVIDE(f1a_2_buf_end = .); } .d_rec { *(.rec_data) rec_data_end = .; } .d_enc_ima { . = rec_data_end; *(.enc_a_data) } .d_enc_mp3 { . = rec_data_end; *(.enc_mp3_data) } /* .d_ima { *(.a_data) } */ } > ram0 _overlay_end = .; .heap_buf ALIGN(4): { PROVIDE(_free_start = .); . = LENGTH(ram0) + ORIGIN(ram0) - 1; PROVIDE(_free_end = .); } > ram0 _ram_end = .; . = ORIGIN(app_code); .app_code ALIGN(4): { app_code_text_begin = .; *startup.o(.text) . = ALIGN(4); *(*.f1a_code) _VERSION_BEGIN = .; KEEP(*(.version)) _VERSION_END = .; *(.debug) *(.debug_const) *(.debug_code) *(.debug_string) /* *memset.o(.text .rodata*) */ /* *memcmp.o(.text .rodata*) */ *(*.text.const) *(*.text) *(.app_root) *(.vm) . = ALIGN(4); _SPI_CODE_START = .; *(.spi_code) . = ALIGN(4); _SPI_CODE_END = .; *(.rodata*) *(.ins) app_code_text_end = .; /* *(.poweroff_text) */ . = ALIGN(4); loop_detect_handler_begin = .; KEEP(*(.loop_detect_region)) loop_detect_handler_end = .; . = ALIGN(4); device_node_begin = .; PROVIDE(device_node_begin = .); KEEP(*(.device)) _device_node_end = .; PROVIDE(device_node_end = .); vfs_ops_begin = .; KEEP(*(.vfs_operations)) vfs_ops_end = .; . = ALIGN(4); lp_target_begin = .; PROVIDE(lp_target_begin = .); KEEP(*(.lp_target)) lp_target_end = .; PROVIDE(lp_target_end = .); app_size = .; /* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */ /* *(.sec.array_maskrom_export) */ . = ALIGN(4); text_end = .; } >app_code bss_begin = ADDR(.bss); bss_size = SIZEOF(.bss); /*除堆栈外的bss区*/ bss_size1 = _system_data_end - _system_data_begin; bss_begin1 = _system_data_begin; data_addr = ADDR(.data) ; data_begin = text_end ; data_size = SIZEOF(.data) + SIZEOF(.debug_data); text_size = SIZEOF(.app_code); _sdk_text_addr = ADDR(.app_code); _sdk_text_size = text_size; _sdk_data_size = data_size; _sdk_overlay_size = _overlay_end - _overlay_start; _sdk_heap_size = _free_end - _free_start; } ```
### 一、简介 AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。 1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的; 2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源 **注1:实现后,提高系统时钟以面对更大的运行压力。** **注2: 此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。 AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别: AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间; AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间; 上面两个版本在申请时,大小是有所区别的;** **注3: 本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)** **注4: 如果要自行修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。** ### 二、方法 1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c) 2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c) 3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c) ### 三、具体实现 1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c) ![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图") ![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图") 2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c) ![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图") 3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c) ![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图") ### 相关源代码: **1、app\bsp\common\decoder\list\f1a_api.c:** ``` #include "f1a_api.h" #include "cpu.h" #include "config.h" #include "typedef.h" //#include "hwi.h" #include "decoder_api.h" //#include "dev_manage.h" #include "vfs.h" //#include "fs.h" #include "circular_buf.h" #include "dac.h" /* #include "resample.h" */ /* #include "speed_api.h" */ #include "msg.h" #include "errno-base.h" #include "decoder_msg_tab.h" #include "app_config.h" #include "decoder_cpu.h" #include "app_modules.h" //#include "avio.h" //#include "bitstream.h" //#include "wmadata.h" #if defined(DECODER_F1A_EN) && (DECODER_F1A_EN) #define LOG_TAG_CONST NORM #define LOG_TAG "[normal]" #include "log.h" bool f1a_type_run; #define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE) #define F1A_DBUF_SIZE (0xc64) #define F1A_OUTPUT_MAX_SIZE (32 * 2) #define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2)) dec_obj dec_f1a_hld[MAX_F1A_CHANNEL]; #if HAS_F1A_MASK_TAB const int cos_tab_split = 1300 / 4; /* const int f1a_cos_maskrom_tab[1] = {0}; */ #else const int cos_tab_split = 0; const int f1a_cos_maskrom_tab[1] = {0}; #endif /*************************************************************/ /* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */ /* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */ /* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */ typedef struct _f1x_data { cbuffer_t cbuf; u16 o_buf[F1A_OBUF_SIZE / 2]; u16 d_buff[F1A_DBUF_SIZE / 2]; } f1x_data; f1x_data g_f1x1_data AT(.f1a_1_buf); f1x_data g_f1x2_data AT(.f1a_2_buf); const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = { { &dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL mp_input, mp_output, }, #if (MAX_F1A_CHANNEL > 1) { &dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL mp_input, mp_output, } #endif }; const char f1a_ext[] = {".f1a"}; const char f1b_ext[] = {".f1b"}; const char f1c_ext[] = {".f1c"}; const char f1x_ext[] = {".f1x"}; extern audio_decoder_ops *get_f1a_ops(); u8 g_loop_tab[10] = { 0, 1, 2, 0, 0, 1, 2, 3, 2, 1 }; u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data) { u32 buff_len, i; decoder_ops_t *ops; /* void *name; */ /* char name[16] = {0}; */ char ctype = 0; log_info("f1a_decode_api"); void *p_cbuf; dec_obj *p_dec_hld; void *p_obuf; void *p_dbuf; void *p_dec_io; if (index >= MAX_F1A_CHANNEL) { return E_F1A_INDEX; } /* p_cbuf = &cbuf_f1a[index]; */ /* p_obuf = &obuf_f1a[index][0]; */ /* p_dbuf = &f1a_decode_buff[index][0]; */ p_cbuf = &p_f1x_data->cbuf; p_obuf = &p_f1x_data->o_buf[0]; p_dbuf = &p_f1x_data->d_buff[0]; p_dec_hld = &dec_f1a_hld[index]; p_dec_io = (void *)&f1a_dec_io[index]; local_irq_disable(); memset(p_dec_hld, 0, sizeof(dec_obj)); local_irq_enable(); dec_f1a_hld[0].type = D_TYPE_F1A_1; #if (MAX_F1A_CHANNEL > 1) dec_f1a_hld[1].type = D_TYPE_F1A_2; #endif ops = get_f1a_ops(); buff_len = ops->need_dcbuf_size(); if (buff_len > F1A_DBUF_SIZE) { log_info("f1a buff need : 0x%x\n", buff_len); return E_F1A_DBUF; } /******************************************/ cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE); /* log_info("A\n"); */ /* log_info("c buffrt 0x%x\n",p_cbuf); */ /* log_info("B\n"); */ p_dec_hld->p_file = p_file; p_dec_hld->sound.p_obuf = p_cbuf; p_dec_hld->sound.para = F1A_KICK_SIZE; p_dec_hld->p_dbuf = p_dbuf; p_dec_hld->dec_ops = ops; p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0]; p_dec_hld->p_dp_buf = p_dp_buf; /* log_info("C\n"); */ // /******************************************/ /* name = vfs_file_name(p_file); */ int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname)); log_info("file name : %s", g_file_sname); u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下 if (check_ext_api(g_file_sname, f1a_ext, 4)) { ctype = 'a'; } else if (check_ext_api(g_file_sname, f1b_ext, 4)) { ctype = 'b'; } else if (check_ext_api(g_file_sname, f1c_ext, 4)) { ctype = 'c'; if (ops->format_check(p_dbuf)) { //格式检查 log_error("f1c format err\n"); return E_F1A_FORMAT; } } else if (check_ext_api(g_file_sname, f1x_ext, 4)) { ctype = 'x'; void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par); if (NULL == pf1x) { log_error("f1x null\n"); return E_F1X_FORMAT; } ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x); if (ops->format_check(p_dbuf)) { //格式检查 log_error("f1x format err\n"); return E_F1A_FORMAT; } } else { log_error("f1a type err\n"); return E_F1A_TYPE; } log_info("file is a f1%c", ctype); regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC; /*************************************************/ /* log_info("E\n"); */ if ('b' == ctype) { i = 32000; } else { i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率 } log_info("file sr : %d\n", i); /* dac_sr_api(i); */ p_dec_hld->sr = i; *p_dec = p_dec_hld; f1a_type_run = 1; return 0; /* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */ /* kick_decoder(); */ /* return 0; */ } //-------------------------------- u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf) { return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data); } u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf) { #if (MAX_F1A_CHANNEL > 1) return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data); #else return E_F1A_OUTRGE; #endif } /* extern const u8 _buf_start[]; */ /* extern const u8 _buf_end[]; */ extern const u8 f1a_1_buf_start[]; extern const u8 f1a_1_buf_end[]; extern const u8 f1a_2_buf_start[]; extern const u8 f1a_2_buf_end[]; u32 f1a_1_buff_api(dec_buf *p_dec_buf) { p_dec_buf->start = (u32)&f1a_1_buf_start[0]; p_dec_buf->end = (u32)&f1a_1_buf_end[0]; return 0; } u32 f1a_2_buff_api(dec_buf *p_dec_buf) { p_dec_buf->start = (u32)&f1a_2_buf_start[0]; p_dec_buf->end = (u32)&f1a_2_buf_end[0]; return 0; } #endif ``` **2、app\bsp\lib\my_malloc.c:** ``` #include "my_malloc.h" /* #define LOG_TAG_CONST HEAP */ #define LOG_TAG_CONST NORM #define LOG_TAG "[malloc]" #include "log.h" /* void *pvPortMalloc( size_t xWantedSize ) */ /* u32 example(u32 dat) */ /* { */ /* if (dat & 0x80) { */ /* dat += 1; */ /* } else { */ /* dat <<= 1; */ /* } */ /* return dat; */ /* } */ const u16 configHEAP_BEST_SIZE = 100; extern bool f1a_type_run; u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf); u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf); void *my_malloc(u32 size, mm_type xType) { void *res; /* return pvPortMalloc(size); */ if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间 log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size); memset(spec_src_tmp_buf1, 0, size); return spec_src_tmp_buf1; } if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) { f1a_type_run = 0; memset(spec_src_tmp_buf2, 0, size); log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size); return spec_src_tmp_buf2; } res = pvPortMalloc(size, xType); if (NULL != res) { log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType); memset(res, 0, size); } else { log_info(" err malloc empty\n"); } return res; } void *my_free(void *pv) { if (pv == spec_src_tmp_buf1) { memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1)); log_info("spec src free!\n"); return NULL; } if (pv == spec_src_tmp_buf2) { memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2)); log_info("spec src free!\n"); return NULL; } if (NULL != pv) { vPortFree(pv); } return NULL; } extern const u8 _free_start[]; extern const u8 _free_end[]; void my_malloc_init(void) { u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1; log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]); memset((void *)&_free_start[0], 0, len); vPortInit((void *)&_free_start[0], len); } void xTaskResumeAll(void) { ; } ``` **3、app\post_build\sh57\voice_toy\app_ld.c:** ``` // *INDENT-OFF* #include "maskrom_stubs.ld" //config _BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24; MEMORY { app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100 ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000 boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24 } ENTRY(_start) SECTIONS { /* L1 memory sections */ . = ORIGIN(boot_ram); .boot_data ALIGN(4): { *(.boot_info) } > boot_ram . = ORIGIN(ram0); .data ALIGN(4): { PROVIDE(data_buf_start = .); *(.data*) *(.*.data) cache_Lx_code_text_begin = .; *(.common) /* *(.ram_code) */ /* *(.volatile_ram_code) */ *(.*.text.cache.L1) *(.*.text.cache.L2) *(.*.text.cache.L3) . = (. + 3) / 4 * 4 ; cache_Lx_code_text_end = .; } > ram0 .debug_data ALIGN(4): { PROVIDE(debug_buf_start = .); *(.debug_bss) *(.debug_data) } > ram0 .bss (NOLOAD) : SUBALIGN(4) { PROVIDE(bss_buf_start = .); . = ALIGN(4); _cpu0_sstack_begin = .; . = ALIGN(4); *(.intr_stack) . = ALIGN(4); *(.stack_magic); . = ALIGN(4); *(.stack) . = ALIGN(4); *(.stack_magic0); . = ALIGN(4); _cpu0_sstack_end = .; . = ALIGN(4); _system_data_begin = .; *(.bss) *(.*.data.bss) *(.non_volatile_ram) . = ALIGN(4); _system_data_end = .; *(.DAC_BUFFER) *(.AUDIO_ADC_BUFFER) } > ram0 /* OVERLAY : */ .effect_buf ALIGN(4): { PROVIDE(effect_buf_start = .); . = ALIGN(4); *(.sp_data) . = ALIGN(4); *(.rs_data) /* .d_sp { *(.sp_data) } */ /* .d_rs { *(.rs_data) } */ } > ram0 /* _ram0_end = .; */ .dec_buf ALIGN(4): { PROVIDE(a_buf_start = .); *(.a_data); PROVIDE(a_buf_end = .); } > ram0 _overlay_start = .; /* . = ORIGIN(ram1); */ OVERLAY : AT(0x200000) { .d_spec_src { PROVIDE(spec_src_buf_start = .); *(.spec_src_buf); PROVIDE(spec_src_buf_end = .); } .d_midi_ctrl { PROVIDE(midi_ctrl_buf_start = .); *(.midi_ctrl_buf); PROVIDE(midi_ctrl_buf_end = .); } .d_midi { PROVIDE(midi_buf_start = .); *(.midi_buf); PROVIDE(midi_buf_end = .); } .d_toy_music { . = spec_src_buf_end; PROVIDE(toy_music_buf_start = .); *(.toy_music_data); PROVIDE(toy_music_buf_end = .); } .d_ump3 { . = toy_music_buf_end; PROVIDE(ump3_buf_start = .); *(.ump3_data); PROVIDE(ump3_buf_end = .); } .d_mp3_st { . = toy_music_buf_end; PROVIDE(mp3_st_buf_start = .); *(.mp3_st_data); PROVIDE(mp3_st_buf_end = .); } .d_wav { . = toy_music_buf_end; PROVIDE(wav_buf_start = .); *(.wav_data); PROVIDE(wav_buf_end = .); } .d_f1a { . = toy_music_buf_end; PROVIDE(f1a_1_buf_start = .); *(.f1a_1_buf); PROVIDE(f1a_1_buf_end = .); PROVIDE(f1a_2_buf_start = .); *(.f1a_2_buf); PROVIDE(f1a_2_buf_end = .); } .d_rec { *(.rec_data) rec_data_end = .; } .d_enc_ima { . = rec_data_end; *(.enc_a_data) } .d_enc_mp3 { . = rec_data_end; *(.enc_mp3_data) } /* .d_ima { *(.a_data) } */ } > ram0 _overlay_end = .; .heap_buf ALIGN(4): { PROVIDE(_free_start = .); . = LENGTH(ram0) + ORIGIN(ram0) - 1; PROVIDE(_free_end = .); } > ram0 _ram_end = .; . = ORIGIN(app_code); .app_code ALIGN(4): { app_code_text_begin = .; *startup.o(.text) . = ALIGN(4); *(*.f1a_code) _VERSION_BEGIN = .; KEEP(*(.version)) _VERSION_END = .; *(.debug) *(.debug_const) *(.debug_code) *(.debug_string) /* *memset.o(.text .rodata*) */ /* *memcmp.o(.text .rodata*) */ *(*.text.const) *(*.text) *(.app_root) *(.vm) . = ALIGN(4); _SPI_CODE_START = .; *(.spi_code) . = ALIGN(4); _SPI_CODE_END = .; *(.rodata*) *(.ins) app_code_text_end = .; /* *(.poweroff_text) */ . = ALIGN(4); loop_detect_handler_begin = .; KEEP(*(.loop_detect_region)) loop_detect_handler_end = .; . = ALIGN(4); device_node_begin = .; PROVIDE(device_node_begin = .); KEEP(*(.device)) _device_node_end = .; PROVIDE(device_node_end = .); vfs_ops_begin = .; KEEP(*(.vfs_operations)) vfs_ops_end = .; . = ALIGN(4); lp_target_begin = .; PROVIDE(lp_target_begin = .); KEEP(*(.lp_target)) lp_target_end = .; PROVIDE(lp_target_end = .); app_size = .; /* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */ /* *(.sec.array_maskrom_export) */ . = ALIGN(4); text_end = .; } >app_code bss_begin = ADDR(.bss); bss_size = SIZEOF(.bss); /*除堆栈外的bss区*/ bss_size1 = _system_data_end - _system_data_begin; bss_begin1 = _system_data_begin; data_addr = ADDR(.data) ; data_begin = text_end ; data_size = SIZEOF(.data) + SIZEOF(.debug_data); text_size = SIZEOF(.app_code); _sdk_text_addr = ADDR(.app_code); _sdk_text_size = text_size; _sdk_data_size = data_size; _sdk_overlay_size = _overlay_end - _overlay_start; _sdk_heap_size = _free_end - _free_start; } ```
评论 (
0
)
Lj-job
创建了
任务
Lj-job
添加了
ram
标签
Lj-job
修改了
标题
原值
FAQ:AD17N同时播放F1A和A会失败异常?保留MIDI+A同时工作,也可以实现F1A+A同时播放
新值
FAQ:AD17N同时播放F1A和A会失败异常?保留MIDI+A同时工作,也可以实现F1A+A同时播放
的方法
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注:实现后,提高系统时钟以面对更大的运行压力。**
**注:此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注:实现后,提高系统时钟以面对更大的运行压力。**
**注:此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
Lj-job
添加了
解码
标签
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注
:实现后,提高系统时钟以面对更大的运行压力。*
*
**注:此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0**
### 二、方法
1、标记F1
A
工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比mi
d
i少出的那部分ram中;(\
a
pp\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
###
相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "
f1a
_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#
include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/
*
#include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "
errno-base.h"
#include "
decoder_msg_tab.h"
#include "
app_config.h"
#include "
deco
de
r_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "
bitstre
a
m.h"
//#include "wmadata.h"
#i
f defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#def
in
e LOG_TAG_CONST
NORM
#def
in
e LOG_TAG
"[normal]"
#include "
lo
g.h"
bool f1a_type_run;
#
define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#
define F1A_DBUF_SIZE (0xc64)
#
define F1A_OUTPUT_MAX_SIZE (32 * 2)
#
define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj
de
c_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split
=
0;
const int f1a_cos_maskrom_tab
[
1] = {0};
#
e
n
dif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX
_
F1A
_
CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode
_
buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE]
A
T(.f1a_buf
)
; */
typedef struct _f1x_data {
cbuffer
_
t cbuf;
u16 o_buf[F1A
_
OBUF_SIZE / 2];
u16 d_buf
f
[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_dat
a
AT(.f1
a
_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if
(MAX_F1A_CHANNEL > 1)
{
&dec_
f
1a_hld[1],
//input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const
char f1a_ext[] = {".f1a"};
const
char f1b_ext[] = {".f1b"};
const
char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio
_
decoder_ops *get_f1a_ops();
u8
g_loop_tab[
1
0] = {
0,
1, 2, 0, 0,
1,
2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
de
c
oder_ops_t *ops;
/* void *name; */
/* char nam
e
[16
] = {
0}; */
char ctype = 0;
log_inf
o
("f1a_dec
o
de_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/*
p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hl
d
= &dec_f1a_hld[index];
p_dec_io = (v
o
id *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec
_
hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if
(MAX
_
F1A_CHANNEL > 1)
de
c
_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a bu
f
f ne
e
d : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_c
b
uf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n");
*/
p_dec_hld->p_file = p_file;
p_dec_hld->sound.
p
_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *
)
&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/*
log_info("C\n"); */
//
/*
******************
*
**********************/
/*
name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name
: %s", g_file_sname);
u32 t
_
par =
o
ps->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (
c
heck_ext_api(g_file_sname, f1a_ext, 4)) {
c
type = 'a';
} else if (check_ext_a
p
i(g_file_sname, f1b_ext, 4)) {
c
type = 'b';
} else if (check_ext_a
p
i(g
_
file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if
(check_
e
xt_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x
= f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error
(
"f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if
(ops->format_check(p_dbuf)) {
//格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
}
else
{
log_error("f1a type err\n");
r
e
turn E_F1A
_
TYPE;
}
log_info("file
is a f1%c", cty
p
e);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/*
l
o
g_info("E\
n
"); */
if
('b' == ctype) {
i
=
32000;
}
else
{
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/*
p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/*
kick_decoder(); */
/*
return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32
f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if
(MAX_F1A_CHANNEL >
1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern
co
nst u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
exte
r
n co
n
st u8 f1a_1
_
buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return
0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
r
etur
n
0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/*
#define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#
i
n
clude "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/
*
{ */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/*
} */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/*
return
pvPortMalloc(size); */
if ((xType ==
MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if
((xType == MM
_
HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type
_
r
u
n = 0;
memse
t
(spec_src_tmp_buf2, 0,
s
ize);
log_info("f1a malloc src2
0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc
res 0x%x, type 0x%x\n",
(u32)res, xType);
memset(res, 0, size);
}
els
e
{
log_i
n
fo(" er
r
malloc empty\n");
}
return res;
}
void
*my_fre
e
(void *pv)
{
if
(pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n"
);
return NULL;
}
if
(pv == sp
e
c_src_tmp_buf2) {
m
e
mset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("
spec
src fre
e
!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern
const u8 _free_start[];
extern const u8 _free_end[];
void
my_
m
alloc_init(void)
{
u32
l
e
n = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *
)
&_free_start[0], 0, len);
vPortIni
t
((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_b
u
ild\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECT
I
ONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code
)
*/
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
.
= (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
}
>
ram0
.debug_data ALIGN(4):
{
PROVIDE(d
e
bug_buf_start = .);
*(.
debug_bss)
*(.debug_data)
} > ram0
.bss
(
NOLOAD) : SUBA
L
IGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.
stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUD
I
O_ADC_BUFFER)
}
>
ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.
sp_data)
. = ALIGN(4);
*(.rs_d
at
a)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
}
>
ram0
/*
_ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
}
>
ram0
_overlay_st
a
rt = .;
/*
. = ORIGI
N(
ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_mi
d
i_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(
midi
_
buf
_
end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music
_
data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(
ump3
_buf_start = .);
*(.
ump3
_
data);
PROVIDE(
ump3
_buf_end = .);
}
.d_
mp3
_
st
{
. =
toy_music_buf_end;
PROVIDE(
mp3
_
st_buf_star
t
= .);
*(.
mp3
_
st_data);
PROVIDE(
mp3
_
st_buf_end = .);
}
.d_
wav
{
. = toy_music_buf_end;
PROVIDE(
wav_buf_start = .);
*(.
wav_data);
PROVIDE(
wav_buf_end = .);
}
.d_
f1a
{
. = toy_music_buf_end;
PROVIDE(
f1a
_
1_buf_start = .);
*(.
f1a
_
1_buf);
PROVIDE(
f1a
_
1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.
enc
_
a
_
data)
}
.d_enc_mp3
{
. = rec_d
a
ta
_
end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
}
>
ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_s
ta
rt = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
}
>
ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.
d
ebug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.
rodata*)
*(.
ins)
app_code
_
text_end = .;
/* *
(.power
o
ff_text) */
. = ALIGN(4);
loop_detec
t
_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device
_
n
ode
_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target
_
en
d
= .;
PROVIDE(lp_target
_
en
d
= .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr
= ADDR(.data) ;
data_begin = t
e
xt_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_
s
dk_text_size
= text_size;
_
s
dk_data_size
= data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_
s
dk_heap_size
= _free_
e
nd - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注
1:实现后,提高系统时钟以面对更大的运行压力。
*
*
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_
A
C104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请以次空间;
上面两个版本在申请时,大小是有所区别;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以结果简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要仔细修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\
d
ecoder\list\f1
a
_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
###
三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给
f1a
的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
#
## 相关源代码:
*
*1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "
f1a_api.h"
#include "
cpu.h"
#include "
config.h"
#include "
type
de
f.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "
dev_man
a
ge.h"
#include "vfs.h"
//#include "fs.h"
#i
nclude "circular_buf.h"
#include "dac.h"
/* #
in
clude "resample.h"
*/
/* #
in
clude "speed_api.h"
*/
#include "
ms
g.h"
#include "errno-base.h"
#
include "decoder_msg_tab.h"
#
include "app_config.h"
#
include "decoder_cpu.h"
#
include "app_modules.h"
//#inclu
de
"avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST
NORM
#define LOG_TAG "
[
normal]"
#
i
n
clude "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT
_
MAX
_
SIZE (32 * 2)
#define F1A_KICK
_
SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_M
A
X_SIZE * 2
)
)
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if
HAS_F1A
_
MASK_TAB
const int cos_tab
_
split = 1300 / 4;
/*
const int
f
1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_m
a
skrom_t
a
b[1] = {0};
#endif
/*************************************************************/
/*
cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/*
u8
obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/*
u8
f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16
d_buf
f
[F1A_DBUF_SIZE
/ 2];
}
f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A
_
CHANNEL > 1)
{
&dec_f
1
a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const
c
har f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_
e
xt[
] = {
".f1c"};
const char f1x_ext[] = {".f1x"};
extern audi
o
_decoder_
o
ps *get_f1a_ops();
u8
g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32
buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/*
char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_
d
buf;
void *p_dec_i
o
;
if (index >= MAX_F1A_CHANNEL) {
return E
_
F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p
_
dbuf = &f1a_decode_buff[index][0]; */
p_
c
buf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&
f
1a_d
e
c_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_ena
b
le();
dec_f1a_hld[0].type
= D_TYPE_F1A_1;
#if
(MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].ty
p
e = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE
)
{
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/*
log_info("A\n");
*
/
/*
log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file =
p_file;
p_dec
_
hld->s
o
und.p_obuf = p_cbuf;
p_de
c
_hld->sound.para = F1A_KICK_SIZE;
p_de
c
_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = o
p
s;
p_de
c
_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf =
p
_dp
_
buf;
/*
log_info("C\n"); */
//
/******************************************/
/* name =
vfs_fil
e
_name(p_file); */
int
file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file
name : %s", g_file_sname);
u32
t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if
(check_ext_api
(
g_file_sname, f1a_ext, 4)) {
ctype = 'a';
}
else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
}
else
if (check_ext_api(g_file_sname,
f1c_ext,
4))
{
ctype = 'c';
if
(ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
}
els
e
if (check
_
ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x
= f1x_play_api(
p
_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
o
ps->dec_co
n
fing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
}
else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*
************************************************/
/*
log_info("E\n"); */
if
('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder();
*/
/* return 0; */
}
//--------------------------------
u32 f1a_de
co
de_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
r
etur
n
f1a_decode
_
index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return
E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/*
extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
exte
r
n co
n
st u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#
e
n
dif
```
*
*2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/*
#define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/*
} else { */
/*
dat
<<= 1;
*/
/* } */
/* return dat;
*/
/*
}
*/
const
u16 configHEAP_BEST_SIZE = 100;
extern
bool f1a_type
_
run;
u32
spec_src_tmp
_
b
u
f1[0x30 / 4] AT(.spec_src_buf);
u32
spec_src_
t
mp_buf2[0x168 / 4] AT(.
s
pec_src_buf);
void
*my_malloc(u32 size, mm_type
xType)
{
void *res;
/* return pvPortMalloc(size); */
if
((xType == MM_SRC) &&
(f1a_type_run == 1)) {
//F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
m
e
mset(spec_src_tmp_buf1, 0, size);
retur
n
spec_s
r
c_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
mems
e
t(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res
= pvPortMalloc(size, xType
);
if
(NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(r
e
s, 0, size);
}
els
e
{
log_info("
err
malloc
e
mpty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
m
emset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
r
e
turn NULL;
}
if (NULL != pv
)
{
vPor
t
Free(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (
u
32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *
I
NDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
.
=
ORIGIN(boot_ram);
.boot_data ALIGN(4
)
:
{
*(.boot_info)
}
>
boot_ram
.
=
ORIGIN(ram0);
.data
ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_t
e
xt_begin = .;
*(.
common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*
(
.*.text.cache.
L
2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
}
>
ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.
debug_data)
}
>
ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = AL
I
GN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.
bss)
*(.*.data.bss)
*(.non_vol
at
ile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/*
OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_d
a
ta)
. = ALIG
N(
4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
}
>
ram0
/*
_ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_
d
ata);
PROVIDE(a_buf_end = .);
}
>
ram0
_overlay_start = .;
/*
. = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(
spec
_
src
_
buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi
_
ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(
midi
_buf_start = .);
*(.
midi
_
buf);
PROVIDE(
midi
_buf_end = .);
}
.d_
toy
_
music
{
. =
spec_src_buf_end;
PROVIDE(
toy
_
music_buf_s
t
art = .);
*(.
toy
_
music_data);
PROVIDE(
toy
_
music_buf_end = .);
}
.d_
ump3
{
. = toy_music_buf_end;
PROVIDE(
ump3_buf_start = .);
*(.
ump3_data);
PROVIDE(
ump3_buf_end = .);
}
.d_
mp3_st
{
. = toy_music_buf_end;
PROVIDE(
mp3
_
st_buf_start = .);
*(.
mp3
_
st_data);
PROVIDE(
mp3
_
st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.
f1a
_
1
_
buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1
a
_2
_
buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_da
ta
)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
}
>
ram0
_ram_en
d
= .;
.
=
ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.
debug_const)
*(.
debug_code)
*(.debug
_
string)
/* *memset.o(.text .rodata*) */
/* *
memcmp.
o
(.text .rodata*) */
*(*.text.const)
*(*.
t
ext)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi
_
c
ode
)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device
_
no
d
e_begin = .;
PROVIDE(device
_
no
d
e_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/*
. = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.s
e
c.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
b
s
s_begin
= ADDR(.bss);
b
s
s_size
= SIZEOF(.bss);
/*除堆栈外的bss区*/
b
s
s_size1
= _syst
e
m_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请
以
次空间;
上面两个版本在申请时,大小是有所区别;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以结果简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要仔细修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请
一
次空间;
上面两个版本在申请时,大小是有所区别;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以结果简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要仔细修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别
;*
*
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以
结果
简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要仔细修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别
的;
*
*
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以
经过
简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要仔细修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别的;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要
仔细
修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别的;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要
自行
修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;()
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
Lj-job
修改了
描述
原值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别的;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要自行修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;(
)
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
新值
### 一、简介
AD17N的RAM资源较少,同时播放F1A和A失败或异常,应该是在需要两路SRC时,第二路SRC不能申请到资源(RAM不够)。
1、由于MIDI和F1A等解码资源是有复用,midi用到资源是会大于F1A等解码的;
2、所以可以在F1A+A工作时,使用解码少出的RAM给F1A格式的SRC使用,第二路SRC不能申请到资源
**注1:实现后,提高系统时钟以面对更大的运行压力。**
**注2:
此文涉及修改是基于AD1x-4578_AC104-release_v1.8.0。
AD1x-4578_AC104-release_v1.8.0与AD1x-457_AC104-release_v1.7.0的SRC申请RAM的区别:
AD1x-4578_AC104-release_v1.8.0为了兼容AD18,每一路SRC会申请两次空间;
AD1x-457_AC104-release_v1.7.0的SRC工作时,每一路SRC只会申请一次空间;
上面两个版本在申请时,大小是有所区别的;**
**注3:
本文所有修改是基于AD1x-4578_AC104-release_v1.8.0,因为‘注2’的原因不能直接使用AD1x-457_AC104-release_v1.7.0(但如果看明白原理,是可以经过简单修改使用到AD1x-457_AC104-release_v1.7.0)**
**注4:
如果要自行修改,为了避免‘注2’‘注3’的影响,在本文涉及的源码app\bsp\lib\my_malloc.c修改中,最好在多加上buffer长度的判断。**
### 二、方法
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
2、定义一些buf给f1a的src使用;(app\bsp\lib\my_malloc.c)
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(app\post_build\sh57\voice_toy\app_ld.c)
### 三、具体实现
1、标记F1A工作状态;(app\bsp\common\decoder\list\f1a_api.c)
![输入图片说明](https://foruda.gitee.com/images/1722505417090887343/b94bc75f_9185836.png "屏幕截图")
![输入图片说明](https://foruda.gitee.com/images/1722505464676248767/b6de07ed_9185836.png "屏幕截图")
2、定义一些buf给f1a的src使用;(
app\bsp\lib\my_malloc.c)
![输入图片说明](https://foruda.gitee.com/images/1722505532337417327/8f6a562c_9185836.png "屏幕截图")
3、将上一步定义的buf在app_ld.c中定位定位到解码比midi少出的那部分ram中;(\app\post_build\sh57\voice_toy\app_ld.c)
![输入图片说明](https://foruda.gitee.com/images/1722505651548589078/4e94cc9a_9185836.png "屏幕截图")
### 相关源代码:
**1、app\bsp\common\decoder\list\f1a_api.c:**
```
#include "f1a_api.h"
#include "cpu.h"
#include "config.h"
#include "typedef.h"
//#include "hwi.h"
#include "decoder_api.h"
//#include "dev_manage.h"
#include "vfs.h"
//#include "fs.h"
#include "circular_buf.h"
#include "dac.h"
/* #include "resample.h" */
/* #include "speed_api.h" */
#include "msg.h"
#include "errno-base.h"
#include "decoder_msg_tab.h"
#include "app_config.h"
#include "decoder_cpu.h"
#include "app_modules.h"
//#include "avio.h"
//#include "bitstream.h"
//#include "wmadata.h"
#if defined(DECODER_F1A_EN) && (DECODER_F1A_EN)
#define LOG_TAG_CONST NORM
#define LOG_TAG "[normal]"
#include "log.h"
bool f1a_type_run;
#define F1A_OBUF_SIZE (DAC_DECODER_BUF_SIZE)
#define F1A_DBUF_SIZE (0xc64)
#define F1A_OUTPUT_MAX_SIZE (32 * 2)
#define F1A_KICK_SIZE (F1A_OBUF_SIZE - (F1A_OUTPUT_MAX_SIZE * 2))
dec_obj dec_f1a_hld[MAX_F1A_CHANNEL];
#if HAS_F1A_MASK_TAB
const int cos_tab_split = 1300 / 4;
/* const int f1a_cos_maskrom_tab[1] = {0}; */
#else
const int cos_tab_split = 0;
const int f1a_cos_maskrom_tab[1] = {0};
#endif
/*************************************************************/
/* cbuffer_t cbuf_f1a[MAX_F1A_CHANNEL] AT(.f1a_buf); */
/* u8 obuf_f1a[MAX_F1A_CHANNEL][F1A_OBUF_SIZE] AT(.f1a_buf); */
/* u8 f1a_decode_buff[MAX_F1A_CHANNEL][F1A_DBUF_SIZE] AT(.f1a_buf); */
typedef struct _f1x_data {
cbuffer_t cbuf;
u16 o_buf[F1A_OBUF_SIZE / 2];
u16 d_buff[F1A_DBUF_SIZE / 2];
} f1x_data;
f1x_data g_f1x1_data AT(.f1a_1_buf);
f1x_data g_f1x2_data AT(.f1a_2_buf);
const struct if_decoder_io f1a_dec_io[MAX_F1A_CHANNEL] = {
{
&dec_f1a_hld[0], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
},
#if (MAX_F1A_CHANNEL > 1)
{
&dec_f1a_hld[1], //input跟output函数的第一个参数,解码器不做处理,直接回传,可以为NULL
mp_input,
mp_output,
}
#endif
};
const char f1a_ext[] = {".f1a"};
const char f1b_ext[] = {".f1b"};
const char f1c_ext[] = {".f1c"};
const char f1x_ext[] = {".f1x"};
extern audio_decoder_ops *get_f1a_ops();
u8 g_loop_tab[10] = {
0, 1, 2, 0, 0,
1, 2, 3, 2, 1
};
u32 f1a_decode_index(void *p_file, u32 index, dec_obj **p_dec, void *p_dp_buf, f1x_data *p_f1x_data)
{
u32 buff_len, i;
decoder_ops_t *ops;
/* void *name; */
/* char name[16] = {0}; */
char ctype = 0;
log_info("f1a_decode_api");
void *p_cbuf;
dec_obj *p_dec_hld;
void *p_obuf;
void *p_dbuf;
void *p_dec_io;
if (index >= MAX_F1A_CHANNEL) {
return E_F1A_INDEX;
}
/* p_cbuf = &cbuf_f1a[index]; */
/* p_obuf = &obuf_f1a[index][0]; */
/* p_dbuf = &f1a_decode_buff[index][0]; */
p_cbuf = &p_f1x_data->cbuf;
p_obuf = &p_f1x_data->o_buf[0];
p_dbuf = &p_f1x_data->d_buff[0];
p_dec_hld = &dec_f1a_hld[index];
p_dec_io = (void *)&f1a_dec_io[index];
local_irq_disable();
memset(p_dec_hld, 0, sizeof(dec_obj));
local_irq_enable();
dec_f1a_hld[0].type = D_TYPE_F1A_1;
#if (MAX_F1A_CHANNEL > 1)
dec_f1a_hld[1].type = D_TYPE_F1A_2;
#endif
ops = get_f1a_ops();
buff_len = ops->need_dcbuf_size();
if (buff_len > F1A_DBUF_SIZE) {
log_info("f1a buff need : 0x%x\n", buff_len);
return E_F1A_DBUF;
}
/******************************************/
cbuf_init(p_cbuf, p_obuf, F1A_OBUF_SIZE);
/* log_info("A\n"); */
/* log_info("c buffrt 0x%x\n",p_cbuf); */
/* log_info("B\n"); */
p_dec_hld->p_file = p_file;
p_dec_hld->sound.p_obuf = p_cbuf;
p_dec_hld->sound.para = F1A_KICK_SIZE;
p_dec_hld->p_dbuf = p_dbuf;
p_dec_hld->dec_ops = ops;
p_dec_hld->event_tab = (u8 *)&f1a_evt[index][0];
p_dec_hld->p_dp_buf = p_dp_buf;
/* log_info("C\n"); */
//
/******************************************/
/* name = vfs_file_name(p_file); */
int file_len = vfs_file_name(p_file, (void *)g_file_sname, sizeof(g_file_sname));
log_info("file name : %s", g_file_sname);
u32 t_par = ops->open(p_dbuf, p_dec_io, p_dp_buf); //传入io接口,说明如下
if (check_ext_api(g_file_sname, f1a_ext, 4)) {
ctype = 'a';
} else if (check_ext_api(g_file_sname, f1b_ext, 4)) {
ctype = 'b';
} else if (check_ext_api(g_file_sname, f1c_ext, 4)) {
ctype = 'c';
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1c format err\n");
return E_F1A_FORMAT;
}
} else if (check_ext_api(g_file_sname, f1x_ext, 4)) {
ctype = 'x';
void *pf1x = f1x_play_api(p_file, g_loop_tab, sizeof(g_loop_tab), index, t_par);
if (NULL == pf1x) {
log_error("f1x null\n");
return E_F1X_FORMAT;
}
ops->dec_confing(p_dbuf, CMD_SET_PLAY_FILE, pf1x);
if (ops->format_check(p_dbuf)) { //格式检查
log_error("f1x format err\n");
return E_F1A_FORMAT;
}
} else {
log_error("f1a type err\n");
return E_F1A_TYPE;
}
log_info("file is a f1%c", ctype);
regist_dac_channel(&p_dec_hld->sound, kick_decoder);//注册到DAC;
/*************************************************/
/* log_info("E\n"); */
if ('b' == ctype) {
i = 32000;
} else {
i = ops->get_dec_inf(p_dbuf)->sr; //获取采样率
}
log_info("file sr : %d\n", i);
/* dac_sr_api(i); */
p_dec_hld->sr = i;
*p_dec = p_dec_hld;
f1a_type_run = 1;
return 0;
/* p_dec_hld->sound.enable = B_DEC_ENABLE | B_DEC_KICK; */
/* kick_decoder(); */
/* return 0; */
}
//--------------------------------
u32 f1a_decode_api_1(void *p_file, void **p_pdec, void *t_dp_buf)
{
return f1a_decode_index(p_file, 0, (dec_obj **)p_pdec, t_dp_buf, &g_f1x1_data);
}
u32 f1a_decode_api_2(void *p_file, void **p_pdec, void *t_dp_buf)
{
#if (MAX_F1A_CHANNEL > 1)
return f1a_decode_index(p_file, 1, (dec_obj **)p_pdec, t_dp_buf, &g_f1x2_data);
#else
return E_F1A_OUTRGE;
#endif
}
/* extern const u8 _buf_start[]; */
/* extern const u8 _buf_end[]; */
extern const u8 f1a_1_buf_start[];
extern const u8 f1a_1_buf_end[];
extern const u8 f1a_2_buf_start[];
extern const u8 f1a_2_buf_end[];
u32 f1a_1_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_1_buf_start[0];
p_dec_buf->end = (u32)&f1a_1_buf_end[0];
return 0;
}
u32 f1a_2_buff_api(dec_buf *p_dec_buf)
{
p_dec_buf->start = (u32)&f1a_2_buf_start[0];
p_dec_buf->end = (u32)&f1a_2_buf_end[0];
return 0;
}
#endif
```
**2、app\bsp\lib\my_malloc.c:**
```
#include "my_malloc.h"
/* #define LOG_TAG_CONST HEAP */
#define LOG_TAG_CONST NORM
#define LOG_TAG "[malloc]"
#include "log.h"
/* void *pvPortMalloc( size_t xWantedSize ) */
/* u32 example(u32 dat) */
/* { */
/* if (dat & 0x80) { */
/* dat += 1; */
/* } else { */
/* dat <<= 1; */
/* } */
/* return dat; */
/* } */
const u16 configHEAP_BEST_SIZE = 100;
extern bool f1a_type_run;
u32 spec_src_tmp_buf1[0x30 / 4] AT(.spec_src_buf);
u32 spec_src_tmp_buf2[0x168 / 4] AT(.spec_src_buf);
void *my_malloc(u32 size, mm_type xType)
{
void *res;
/* return pvPortMalloc(size); */
if ((xType == MM_SRC) && (f1a_type_run == 1)) { //F1A申请空间
log_info("f1a malloc src 0x%x!!!!!!!!!!!!!\n",size);
memset(spec_src_tmp_buf1, 0, size);
return spec_src_tmp_buf1;
}
if ((xType == MM_HW_SRC_BUF) && (f1a_type_run == 1)) {
f1a_type_run = 0;
memset(spec_src_tmp_buf2, 0, size);
log_info("f1a malloc src2 0x%x !!!!!!!!!\n",size);
return spec_src_tmp_buf2;
}
res = pvPortMalloc(size, xType);
if (NULL != res) {
log_info(" malloc res 0x%x, type 0x%x\n", (u32)res, xType);
memset(res, 0, size);
} else {
log_info(" err malloc empty\n");
}
return res;
}
void *my_free(void *pv)
{
if (pv == spec_src_tmp_buf1) {
memset(spec_src_tmp_buf1, 0, sizeof(spec_src_tmp_buf1));
log_info("spec src free!\n");
return NULL;
}
if (pv == spec_src_tmp_buf2) {
memset(spec_src_tmp_buf2, 0, sizeof(spec_src_tmp_buf2));
log_info("spec src free!\n");
return NULL;
}
if (NULL != pv) {
vPortFree(pv);
}
return NULL;
}
extern const u8 _free_start[];
extern const u8 _free_end[];
void my_malloc_init(void)
{
u32 len = (u32)&_free_end[0] - (u32)&_free_start[0] + 1;
log_info(" HEAP----: 0x%x; 0x%x\n", (u32)&_free_end[0], (u32)&_free_start[0]);
memset((void *)&_free_start[0], 0, len);
vPortInit((void *)&_free_start[0], len);
}
void xTaskResumeAll(void)
{
;
}
```
**3、app\post_build\sh57\voice_toy\app_ld.c:**
```
// *INDENT-OFF*
#include "maskrom_stubs.ld"
//config
_BOOT_RAM_BEGIN = _MASK_EXPORT_MEM_BEGIN - 0x24;
MEMORY
{
app_code(rx) : ORIGIN = 0x4000100, LENGTH = 64M-0x100
ram0(rw) : ORIGIN = 0x3f01000, LENGTH = _BOOT_RAM_BEGIN - 0x3f01000
boot_ram(rw) : ORIGIN = _BOOT_RAM_BEGIN, LENGTH = 0x24
}
ENTRY(_start)
SECTIONS
{
/* L1 memory sections */
. = ORIGIN(boot_ram);
.boot_data ALIGN(4):
{
*(.boot_info)
} > boot_ram
. = ORIGIN(ram0);
.data ALIGN(4):
{
PROVIDE(data_buf_start = .);
*(.data*)
*(.*.data)
cache_Lx_code_text_begin = .;
*(.common)
/* *(.ram_code) */
/* *(.volatile_ram_code) */
*(.*.text.cache.L1)
*(.*.text.cache.L2)
*(.*.text.cache.L3)
. = (. + 3) / 4 * 4 ;
cache_Lx_code_text_end = .;
} > ram0
.debug_data ALIGN(4):
{
PROVIDE(debug_buf_start = .);
*(.debug_bss)
*(.debug_data)
} > ram0
.bss (NOLOAD) : SUBALIGN(4)
{
PROVIDE(bss_buf_start = .);
. = ALIGN(4);
_cpu0_sstack_begin = .;
. = ALIGN(4);
*(.intr_stack)
. = ALIGN(4);
*(.stack_magic);
. = ALIGN(4);
*(.stack)
. = ALIGN(4);
*(.stack_magic0);
. = ALIGN(4);
_cpu0_sstack_end = .;
. = ALIGN(4);
_system_data_begin = .;
*(.bss)
*(.*.data.bss)
*(.non_volatile_ram)
. = ALIGN(4);
_system_data_end = .;
*(.DAC_BUFFER)
*(.AUDIO_ADC_BUFFER)
} > ram0
/* OVERLAY : */
.effect_buf ALIGN(4):
{
PROVIDE(effect_buf_start = .);
. = ALIGN(4);
*(.sp_data)
. = ALIGN(4);
*(.rs_data)
/* .d_sp { *(.sp_data) } */
/* .d_rs { *(.rs_data) } */
} > ram0
/* _ram0_end = .; */
.dec_buf ALIGN(4):
{
PROVIDE(a_buf_start = .);
*(.a_data);
PROVIDE(a_buf_end = .);
} > ram0
_overlay_start = .;
/* . = ORIGIN(ram1); */
OVERLAY : AT(0x200000)
{
.d_spec_src
{
PROVIDE(spec_src_buf_start = .);
*(.spec_src_buf);
PROVIDE(spec_src_buf_end = .);
}
.d_midi_ctrl
{
PROVIDE(midi_ctrl_buf_start = .);
*(.midi_ctrl_buf);
PROVIDE(midi_ctrl_buf_end = .);
}
.d_midi
{
PROVIDE(midi_buf_start = .);
*(.midi_buf);
PROVIDE(midi_buf_end = .);
}
.d_toy_music
{
. = spec_src_buf_end;
PROVIDE(toy_music_buf_start = .);
*(.toy_music_data);
PROVIDE(toy_music_buf_end = .);
}
.d_ump3
{
. = toy_music_buf_end;
PROVIDE(ump3_buf_start = .);
*(.ump3_data);
PROVIDE(ump3_buf_end = .);
}
.d_mp3_st
{
. = toy_music_buf_end;
PROVIDE(mp3_st_buf_start = .);
*(.mp3_st_data);
PROVIDE(mp3_st_buf_end = .);
}
.d_wav
{
. = toy_music_buf_end;
PROVIDE(wav_buf_start = .);
*(.wav_data);
PROVIDE(wav_buf_end = .);
}
.d_f1a
{
. = toy_music_buf_end;
PROVIDE(f1a_1_buf_start = .);
*(.f1a_1_buf);
PROVIDE(f1a_1_buf_end = .);
PROVIDE(f1a_2_buf_start = .);
*(.f1a_2_buf);
PROVIDE(f1a_2_buf_end = .);
}
.d_rec
{
*(.rec_data)
rec_data_end = .;
}
.d_enc_ima
{
. = rec_data_end;
*(.enc_a_data)
}
.d_enc_mp3
{
. = rec_data_end;
*(.enc_mp3_data)
}
/* .d_ima { *(.a_data) } */
} > ram0
_overlay_end = .;
.heap_buf ALIGN(4):
{
PROVIDE(_free_start = .);
. = LENGTH(ram0) + ORIGIN(ram0) - 1;
PROVIDE(_free_end = .);
} > ram0
_ram_end = .;
. = ORIGIN(app_code);
.app_code ALIGN(4):
{
app_code_text_begin = .;
*startup.o(.text)
. = ALIGN(4);
*(*.f1a_code)
_VERSION_BEGIN = .;
KEEP(*(.version))
_VERSION_END = .;
*(.debug)
*(.debug_const)
*(.debug_code)
*(.debug_string)
/* *memset.o(.text .rodata*) */
/* *memcmp.o(.text .rodata*) */
*(*.text.const)
*(*.text)
*(.app_root)
*(.vm)
. = ALIGN(4);
_SPI_CODE_START = .;
*(.spi_code)
. = ALIGN(4);
_SPI_CODE_END = .;
*(.rodata*)
*(.ins)
app_code_text_end = .;
/* *(.poweroff_text) */
. = ALIGN(4);
loop_detect_handler_begin = .;
KEEP(*(.loop_detect_region))
loop_detect_handler_end = .;
. = ALIGN(4);
device_node_begin = .;
PROVIDE(device_node_begin = .);
KEEP(*(.device))
_device_node_end = .;
PROVIDE(device_node_end = .);
vfs_ops_begin = .;
KEEP(*(.vfs_operations))
vfs_ops_end = .;
. = ALIGN(4);
lp_target_begin = .;
PROVIDE(lp_target_begin = .);
KEEP(*(.lp_target))
lp_target_end = .;
PROVIDE(lp_target_end = .);
app_size = .;
/* . = LENGTH(app_code) - LENGTH_OF_ENTRY_LIST; */
/* *(.sec.array_maskrom_export) */
. = ALIGN(4);
text_end = .;
} >app_code
bss_begin = ADDR(.bss);
bss_size = SIZEOF(.bss);
/*除堆栈外的bss区*/
bss_size1 = _system_data_end - _system_data_begin;
bss_begin1 = _system_data_begin;
data_addr = ADDR(.data) ;
data_begin = text_end ;
data_size = SIZEOF(.data) + SIZEOF(.debug_data);
text_size = SIZEOF(.app_code);
_sdk_text_addr = ADDR(.app_code);
_sdk_text_size = text_size;
_sdk_data_size = data_size;
_sdk_overlay_size = _overlay_end - _overlay_start;
_sdk_heap_size = _free_end - _free_start;
}
```
展开全部操作日志
折叠全部操作日志
登录
后才可以发表评论
状态
待办的
待办的
进行中
已完成
已关闭
负责人
未设置
标签
ram
解码
未设置
标签管理
里程碑
未关联里程碑
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
分支 (1)
标签 (10)
main
AD1x-4578_AC104-release_v1.8.0
AD1x-457_AC104-release_v1.7.0
ad14n_ad15n_ac104n-release_v1.6.0
ad14n-ad15n-release_V1.5.1
ad14n-ad15n-release_V1.5.0
ad14n-ad15n-release_V1.4.0
ad14n-ad15n-release_V1.3.0
ad14n-ad15n-release_V1.2.2
ad14n-ad15n-release_V1.1.0
ad150-release_V1.0.2
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
参与者(1)