




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
嵌入式軟件開發(fā)嵌入式開發(fā)過程“PC軟件”獨(dú)立的嵌入式應(yīng)用當(dāng)程序員開始開發(fā)一個(gè)基于ARM應(yīng)用的時(shí)候,你可以使用ARM的ADS編寫類似于“HELLOWORLD”的程序,使用ARMulator或者在評(píng)估板上來(lái)調(diào)試,但當(dāng)你把他移植到獨(dú)立的嵌入式應(yīng)用設(shè)備中時(shí),下面這些問題就成為我們首要考慮的:
硬件環(huán)境中所使用的C庫(kù)函數(shù)
目標(biāo)板上的存儲(chǔ)器資源
應(yīng)用程序的初始化議程PC軟件的構(gòu)造
定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板
復(fù)位和初始化
深層次的存儲(chǔ)器器映象考慮
編譯和調(diào)試IMAGEADS默認(rèn)的存儲(chǔ)器映射在默認(rèn)的情況下,我們鏈接、定位、運(yùn)行在0x8000heap被直接放置在數(shù)據(jù)區(qū)的上面堆棧的基地址是通過調(diào)試環(huán)境從C庫(kù)函數(shù)的StartupCode里讀取出來(lái)的。ARMulator=>fromconfigurationfile(peripherals.ami)default=0x08000000Multi-ICE=>fromdebuggerinternalvariable$top_of_memorydefault=0x80000RORWZI0x8000鏈接時(shí)確定由調(diào)試環(huán)境提供Heap(malloc,alloc)StackCLibraryUserCode應(yīng)用程序啟動(dòng)__maincopycodeanddatazerouninitializeddata__rt_entrysetupapplicationstackandheapinitializelibraryfunctionscalltop-levelconstructors(C++)Exitfromapplicationmain()causesthelinkertopullinlibraryinitializationcode程序入口點(diǎn)Agenda 一個(gè)PC軟件的構(gòu)造
定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板
復(fù)位和初始化
深層次的存儲(chǔ)器器映象考慮
編譯和調(diào)試IMAGE重定向C庫(kù)函數(shù)(2)要重定向C庫(kù)函數(shù),簡(jiǎn)單的辦法是使用你自己的可執(zhí)行的semihostingSWIs來(lái)代替原來(lái)的C庫(kù)函數(shù),從而來(lái)滿足你的系統(tǒng)要求
比如說(shuō),theprintf()系列函數(shù)(sprintf()除外)都會(huì)調(diào)用fputc().在默認(rèn)情況下fputc()的執(zhí)行使用了semihostingSWI.用下面的語(yǔ)句來(lái)代替:
externvoidsendchar(char*ch);
intfputc(intch,FILE*f)
{/*e.g.writeacharactertoanLCD*/
chartempch=ch;
sendchar(&tempch);
returnch;
}
可查看在ADSEmbeddedexample目錄下的retarget.c,可看到更多的重定向例子
你可以確定有不在連接時(shí)使用semihostingSWI的嗎?…...消除C庫(kù)函數(shù)中的semihosting為了確保在連接時(shí)沒有函數(shù)使用了semihostingSWIs,你可以在程序中加入下面的句子:#pragmaimport(__use_no_semihosting_swi)
如果在程序中仍然使用了semihosting,編譯時(shí)將會(huì)報(bào)錯(cuò):Error:Symbol__semihosting_swi_guardmultiplydefined修改:
如果使用(check-verboselinkeroutputforoccurrencesofIuse_semihosting_swi),那么連接器將會(huì)把那些使用了smeihosting的程序列出來(lái),
然后:提供你自己可運(yùn)行的功能函數(shù)。在ADS1.2編譯器和庫(kù)函數(shù)手冊(cè),表4-2給出了所有使用了semihosting的C庫(kù)函數(shù)。注意:連接器在用戶自己的應(yīng)用代碼中不會(huì)出現(xiàn)任何有關(guān)semihostingSWI使用的報(bào)告。Agenda
一個(gè)PC軟件的構(gòu)造
定制標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板
定制IMAGE的存儲(chǔ)器映射到目標(biāo)板
復(fù)位和初始化
深層次的存儲(chǔ)器器映象考慮
編譯和調(diào)試IMAGEExecuteViewRAM0x100000x180000x40000x0000ROMRO分散加載
(簡(jiǎn)單例子)只讀代碼和數(shù)據(jù)保存在ROM中C庫(kù)函數(shù)初始化代碼(在__main)將:從ROM拷貝RW數(shù)據(jù)到RAM在RAM中的ZI數(shù)據(jù)初始化RAM0x100000x180000x40000x0000ROMLoadViewRORWFillwithzerosZICopyRWExecuteViewRAM0x100000x180000x40000x0000ROMROLOAD_ROM0x00000x4000{}RAM0x100000x180000x40000x0000ROMLoadViewRORWScatter描述文件通配符(*)語(yǔ)法允許簡(jiǎn)單的對(duì)CODE和DATA進(jìn)行分組EXEC_ROM0x00000x4000{*(+RO)}RAM0x100000x8000{*(+RW,+ZI)}RWZIRORWZIROCODERO-DATARO-CODEAB鏈接器放置規(guī)則在每個(gè)可執(zhí)行區(qū),鏈接器通過一些基本的規(guī)則來(lái)放置CODE和DATA基本的排序方法是通過屬性來(lái)安排的:RO領(lǐng)先于RW,RW領(lǐng)先于ZI有相同的屬性時(shí),CODE在DATA之前放置。更多的排序方法決定于:輸入的組名按字母排序,
在ARMLINK命令行中指定的順序。eg:armlink…
AsectionAfromsectionAfromROOT區(qū)
LOAD_ROM0x00000x4000;startaddressandlength
{ EXEC_ROM0x00000x4000;root(load=execaddress){
__main.o(+RO);copyingcode*(Region$$Table);RO/RWaddressestocopy*(ZISection$$Table);ZIaddressestozero }
RAM0x100000x8000
{
*(+RO);AllotherROareas *(+RW,+ZI);programvariables
}
}Mustbeinarootregionoutsiderootregion一個(gè)root區(qū)是一個(gè)可執(zhí)行區(qū),它的加載地址等于執(zhí)行地址。Root區(qū)要點(diǎn)一個(gè)root區(qū)是一個(gè)可執(zhí)行區(qū),它的加載地址等于執(zhí)行地址.每個(gè)scatter描述文件必須最少包含一個(gè)root區(qū),并且最少要包含下列內(nèi)容:__main.o–含有拷貝code/data的代碼Region$$Table和ZISection$$Table–含有將要拷貝的code/data的地址,他是由鏈接器產(chǎn)生的,不是一個(gè)對(duì)象文件。(所以*必須用)
Error:L6202E:SectionRegion$$Tablecannotbeassignedtoanon-rootregion. Error:L6202E:SectionZISection$$Tablecannotbeassignedtoanon-rootregion.注意:如果
*(+RO)被定位在root區(qū),在此之前的將被自動(dòng)放置Main應(yīng)用程序的入口點(diǎn)必須放在root區(qū)。 Error:L6203E:Entrypoint(0x08000000)lieswithinnon-rootregionEXE_FLASH.Run-time存儲(chǔ)器管理SemihostingSupportANSICStack&HeapSetupStack&HeapSetupANSICCLibraryUserCodeDebugAgentTargetHardwareRetarget如何設(shè)置stack和heap來(lái)滿足我們的目標(biāo)存儲(chǔ)器?我們已經(jīng)通過執(zhí)行__user_initial_stackheap()把C標(biāo)準(zhǔn)庫(kù)的運(yùn)行存儲(chǔ)器模式修改到目標(biāo)平臺(tái)上。Run-time存儲(chǔ)器模式你必須決定在放置stack和heap時(shí)所使用的區(qū)域是單一的區(qū)(one-regionmodel)或是不同的兩個(gè)區(qū)(two-regionmodel)HeapStackStackOneregionmodelTworegionmodelHBSBSBHBHL單一存儲(chǔ)器模式是默認(rèn)方式為了實(shí)現(xiàn)多區(qū)域模式,你可以使用use_two_region_memory在所有的模式下,軟件堆棧檢查要許可。編譯開關(guān)是:-apcs/swst指定堆棧限制(為two-region模式)heapischeckedagainststackpointerHeapheapischeckedagainstheaplimit(SL)__user_initial_stackheap()可以用C或匯編來(lái)寫,他要返回:Heap基地址在R0,STACK的基地址在R1.Heap的限制地址在R2,STACK的限制地址在R3
EXPORT__user_initial_stackheap__user_initial_stackheap LDRr0,=0x80000;HB LDRr1,=0x88000;SB ;r2notused(HL) ;r3notused(SL) MOVpc,lrHeapStackHeap的限制地址在單一模式是不被使用的。Stack的限制地址只在軟件堆棧檢查許可的情況下才有效。HB=0x80000SB=0x88000警告!當(dāng)使用分散加載時(shí)你必須執(zhí)行__user_initial_stackheap()在C庫(kù)初始化代碼內(nèi)的__user_initial_stackheap()的默認(rèn)執(zhí)行是在映像文件的RW/ZI數(shù)據(jù)段后放置HEAP。使用Image$$RW$$Base/Image$$ZI$$Base
連接符號(hào)這些符號(hào)對(duì)scatterloading是無(wú)效的。在ADS1.1和早期版本的軟件中:符號(hào)被設(shè)置為0X0,heap被定位在這!Heap的并發(fā)使用,無(wú)論是直接(e.g.withmalloc())或間接(byuseofargc/argv)的都可能破壞向量表或其他代碼,典型的結(jié)果是不可預(yù)知的程序在運(yùn)行時(shí)出錯(cuò)了。在ADS1.2:符號(hào)沒有定義,應(yīng)用程序不會(huì)聯(lián)接:
Error:L6218E:UndefinedsymbolImage$$ZI$$Limit(referredfromsys_stackheap.o).TheVectorTable
AREAVectors,CODE,READONLY IMPORTReset_Handler
;importotherexceptionhandlers ;…ENTRY B Reset_Handler
B Undefined_Handler
B SWI_Handler
B Prefetch_Handler
B Data_Handler
NOP ;Reservedvector
B IRQ_Handler
;FIQ_Handlerwillfollowdirectly END在使用scatterloading+FIRST時(shí)直接定位在0X0(或0xFFFF0000)ENTRY
直接告訴鏈接器這是一個(gè)入口點(diǎn),防止某些段被刪除中斷向量表初始化步驟CLibraryUserCode__maincopycodeanddatazerouninitializeddata__rt_entryinitializelibraryfunctionscalltop-levelconstructors(C++)Exitfromapplicationmain()tellslinkertolinkinlibraryinitializationcodeImageEntryPoint__user_initial_stackheap()setupstack&heapresethandlerinitializestackpointersconfigureMMU/MPUsetupcache/enableTCM$Sub$$main()enablecaches&interrupts初始化棧的指針;---Amountofmemory(inbytes)allocatedforstacksLen_FIQ_StackEQU256Len_IRQ_StackEQU256…Offset_FIQ_StackEQU0Offset_IRQ_StackEQUOffset_FIQ_Stack+Len_FIQ_Stack…Reset_HandlerLDRr0,stack_base;locatedbyscatterfile;EntereachmodeinturnandsetupthestackpointerMSRCPSR_c,#Mode_FIQ:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_FIQ_StackMSRCPSR_c,#Mode_IRQ:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_IRQ_Stack
…;SystemmodestackissetuplastMSRCPSR_c,#Mode_SYS:OR:I_Bit:OR:F_Bit;NointerruptsSUBsp,r0,#Offset_SYS_Stack;SetupstacklimitifneededLDRr10,stack_limit;locatedbyscatterfile
局部存儲(chǔ)器設(shè)置run-time的存儲(chǔ)器必須在C庫(kù)初始化前定義如果你使用的ARM7芯片還有MMU/MPU,它必須設(shè)置;ROM/RAM的重新映射必須完成。TCM’s(Tightlycoupledmemory)如果有TCM,典型的必須使能它。請(qǐng)注意:在TCM使能之前,要屏蔽ROM在Cache打開之前要返回。在c庫(kù)初始化代碼運(yùn)行之后,如果cache被使能,可以避免與cache相關(guān)的問題;擴(kuò)展功能系統(tǒng)初始化代碼通常在進(jìn)入主應(yīng)用之前運(yùn)行當(dāng)然,resethandler不是一個(gè)適合使能中斷和使能caches地方。在resethandler最后應(yīng)該放一個(gè)C運(yùn)行庫(kù)初始化代碼EG。IMPORT__main B__main我們可使用$Sub和$Super功能來(lái)包裝符號(hào)externvoid$Super$$main(void);void$Sub$$main(void){cache_enable(); //enablescachesint_enable(); //enablesinterruptssys_to_usr_mode(); //changemode-seenextslide$Super$$main(); //callsoriginalmain()}相關(guān)描述可在ADS1.2LinkerandUtilitiesGuide-4.4章查閱到。運(yùn)行模式考慮主應(yīng)用程序運(yùn)行在何種模式是要考慮的重要問題。用戶模式(Usermode)是非特權(quán)模式(unprivilegedmode)-保護(hù)你的系統(tǒng)系統(tǒng)初始化代碼只能運(yùn)行在特權(quán)模式(privilegedmode)。需要執(zhí)行特權(quán)操作比如:使能中斷。如果你的應(yīng)用要運(yùn)行在管理模式,簡(jiǎn)單的在管理模式下退出你的resethandler就可。如果你想在用戶模式下運(yùn)行你的應(yīng)用,你需在$Sub$$main()改變?yōu)橛脩裟J疆?dāng)然,__user_initial_stackheap()必須有權(quán)使用你的應(yīng)用模式寄存器。解決辦法是在系統(tǒng)模式里退出resethandler所有C庫(kù)初始化代碼有權(quán)使用用戶寄存器,但是仍然可以執(zhí)行特權(quán)操作。Agenda 一個(gè)PC軟件的構(gòu)造
裁減標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板
復(fù)位和初始化
深層次的存儲(chǔ)器器映象考慮
編譯和調(diào)試IMAGE長(zhǎng)跳轉(zhuǎn)VeneersROM_LOAD0x0000{ROM_EXEC0x0000{*(+RO) }RAM0x80000000{farfunc.o(+RO)*(+RW,+ZI)}}/*main.c*/
intmain(void)
{
farfunc();
}/*farfunc.c*/
voidfarfunc(void);
{
:
}代碼段可被遠(yuǎn)距離分開放置(比BL的跳轉(zhuǎn)范圍還遠(yuǎn))鏈接器可自動(dòng)增加長(zhǎng)跳轉(zhuǎn)Veneers,遠(yuǎn)距離的函數(shù)可被成功調(diào)用。0x00000000
blVen$AA$L$$farfunc : :Ven$AA$L$$farfunc
ldrpc,[pc,#-4]
dcd0x80000000 : :0x80000000
: movpc,lr存儲(chǔ)器映射寄存器你可以使用scatterloading來(lái)放置外設(shè)寄存器的存儲(chǔ)器映射在文件中定義它e.g.timer_reg.c struct{ volatileunsignedreg1;/*timercontrol*/ volatileunsignedreg2;/*timervalue*/ }timer_reg;
在存儲(chǔ)器映射的請(qǐng)求地址上增加另外的可執(zhí)行區(qū)來(lái)放置他們:
LOAD_FLASH0x240000000x04000000 { : TIMER0x40000000UNINIT { timer_reg.o(+ZI) } : }
UNINIT
顯示在ZI段沒有被初始化為0。Stack和Heap區(qū)(1)你也可以在SCATTER文件中放置stack和heap在匯編原文件里定義stack和heap區(qū)
比如.stackheap.s這個(gè)空間直接保留一個(gè)為0的存儲(chǔ)器塊 AREAstack,DATA,NOINIT SPACE0x3000;Reservestackspace
AREAheap,DATA,NOINIT SPACE0x3000;Reserveheapspace ENDStack和Heap區(qū)(2)增加一個(gè)可執(zhí)行區(qū)來(lái)定位這個(gè)區(qū)域LOAD_FLASH0X240000000x04000000{ : STACK0x1000UNINIT;length=0x3000 {stackheap.o(stack);stack=0x4000to0x1000 } HEAP0x15000UNINIT;length=0x3000 {stackheap.o(heap);heap=0x15000to0x18000 } }Heap的基地址起始為0x15000.Stack的最大地址為0x4000.Stack和Heap區(qū)(3)鏈接器將產(chǎn)生一個(gè)為每個(gè)可執(zhí)行區(qū)的基地址和限制地址的符號(hào)指針在你的代碼中引入這些符號(hào) IMPORT ||Image$$STACK$$ZI$$Base|| IMPORT||Image$$STACK$$ZI$$Limit|| IMPORT||Image$$HEAP$$ZI$$Base|| IMPORT||Image$$HEAP$$ZI$$Limit|| stack_base DCD||Image$$STACK$$ZI$$Limit|| stack_limit DCD||Image$$STACK$$ZI$$Base|| heap_base DCD||Image$$HEAP$$ZI$$Base|| heap_limit DCD||Image$$HEAP$$ZI$$Limit||使用DCD指令為這些段命名__user_initial_stackheap()在resethandler,這個(gè)stack指針(r13)和stack限制值(r10)通常設(shè)置了,他們分別通過R1和R3作為參數(shù)傳遞給__user_initial_stackheap
IMPORT__use_two_region_memory EXPORT__user_initial_stackheap__user_initial_stackheap LDRr0,heap_base ;SBvaluesetupinresethandler LDRr2,heap_limit ;SLvaluesetupinresethandler MOVpc,lrStackHeap這個(gè)__user_initial_stackheap()例子實(shí)現(xiàn)了兩個(gè)存儲(chǔ)器區(qū)域模式。
必須引用
__use_two_region_memory,在這HEAP被檢查,它是HEAP的限制值,而不是STACK指針存儲(chǔ)器映射例子16bitRAM0x100000x180000x40000x0000Fast32bitRAMVectorTableStackExceptionHandlersRW&ZIHeapFlash0x240000000x28000000ResetHandlerROPeripherals0x40000000外設(shè)控制寄存器的地址映射直接在FLASH運(yùn)行的代碼大小16位RAM被用來(lái)保存數(shù)據(jù)和HEAP區(qū)一些緊急的代碼和數(shù)據(jù)可放在快速的RAM區(qū)SCATTER文件例子::16bitRAM0x10000{*(+RW,+ZI)}HEAP0x15000UNINIT{stackheap.o(heap)}
TIMER0x40000000UNINIT{timer_reg.o(+ZI)}}FLASH0x240000000x04000000{FLASH0x240000000x04000000{init.o(Init,+First)*(+RO)}32bitRAM0x0000{vectors.o(Vect,+First)handlers.o(+RO)}STACK0x1000UNINIT{stackheap.o(stack)} :這個(gè)scatter文件執(zhí)行上頁(yè)所顯示的存儲(chǔ)器映射。Agenda 一個(gè)PC軟件的構(gòu)造
裁減標(biāo)準(zhǔn)C庫(kù)函數(shù)到目標(biāo)板定制IMAGE的存儲(chǔ)器映射到目標(biāo)板
復(fù)位和初始化
深層次的存儲(chǔ)器器映象考慮
編譯和調(diào)試IMAGE不使用段的消除和程序的入口點(diǎn)在默認(rèn)的情況下,鏈接器將從最終的image文件中刪除一些從不使用的代碼段,或從未使用的數(shù)據(jù)段。要查看哪些段被刪除了,在鏈接時(shí)用:
‘-infounused’.為了確保不刪除重要的段(比如:中斷向量表):使用匯編指令entry標(biāo)示所有的入口點(diǎn)(c庫(kù)有一個(gè)入口點(diǎn):__main()),使用‘-entry’選擇其中一個(gè)入口點(diǎn)作為image的入口,否則,鏈接器將給警告:
Imagedoesnothaveanentrypoint.(Notspecifiedor
notsetduetomultiplechoices)在生成ROMmableimage使推薦使用下面的鏈接命令:
armlinkobj1.oobj2.o-scatterscatter.scf
-infounused-entry0x0-oprog.axf
輸出選項(xiàng)鏈接器產(chǎn)生ELF/DWARF2格式的映像文件,選擇適當(dāng)?shù)恼{(diào)試器下載調(diào)試為把elf映像文件轉(zhuǎn)為‘ROMmable’格式使用
fromelf,例如.:
fromelfimage.axf-bin-o
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 中西醫(yī)結(jié)合標(biāo)準(zhǔn)化診療方案
- 向陽(yáng)花開:家園共育中的高質(zhì)量陪伴實(shí)踐
- 中西醫(yī)結(jié)合在心血管疾病中的應(yīng)用
- 針灸推拿學(xué)在整形美容中的應(yīng)用
- 中秋節(jié)的詩(shī)歌與祝福
- 卵巢囊腫切除術(shù)操作規(guī)范講解
- 江蘇省鹽城市大豐區(qū)共同體重點(diǎn)達(dá)標(biāo)名校2025屆初三第四次模擬考試(5月)數(shù)學(xué)試題含解析
- 秋季換季期間的皮膚護(hù)理需求
- 山西省晉城市介休一中2025年高三下學(xué)期生物試題統(tǒng)練(5)試題含解析
- 汽車品牌形象推廣策略
- 2025年中考數(shù)學(xué)分類復(fù)習(xí):銳角三角函數(shù)及其應(yīng)用(56題)(原卷版)
- 湖北省襄陽(yáng)襄城區(qū)四校聯(lián)考2025屆中考化學(xué)模擬試卷含解析
- 100以內(nèi)加減法練習(xí)題
- 微訓(xùn)練 一文多考 備考高效之小說(shuō)《十八歲的李響》蔡楠-教師版
- 課件:《科學(xué)社會(huì)主義概論(第二版)》第四章
- 2025年上半年江蘇省蘇州市總工會(huì)招錄社會(huì)化工會(huì)工作者18人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 工廠廢料運(yùn)輸清理協(xié)議
- 2025超市出兌合同書模板
- 《基于寧德時(shí)代的財(cái)務(wù)報(bào)表的公司財(cái)務(wù)分析》4100字(論文)
- 湖南省長(zhǎng)沙市雅禮實(shí)驗(yàn)中學(xué)-主題班會(huì)-《陽(yáng)光心態(tài)美麗青春》【課件】
- 提高單病種上報(bào)率
評(píng)論
0/150
提交評(píng)論