版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、.ADS1 2進行嵌入式軟件開發(fā) jepsen1 新浪嵌入式應用程序通常都是在樣機環(huán)境下調(diào)試與開發(fā)的,這種環(huán)境與最終產(chǎn)品之間并不完全一樣。因此,在系統(tǒng)調(diào)試階段就考慮應用程序在最終目的硬件中的運行情況是非常重要的。本文旨在討論怎么將一個開發(fā)/調(diào)試環(huán)境下的嵌入式應用程序轉移到最終獨立運行的目的系統(tǒng)中去,并提到了ARM ADS1.2開發(fā)工具包的一些功能特性及其在這個過程中所起到的作用。使用ADS開發(fā)嵌入式程序時,需要著重考慮以下幾個提出問題:1.與硬件相關的C語言庫函數(shù)的使用;2.某些C語言庫函數(shù)使用了調(diào)試環(huán)境中的資源,要把這些使用的資源重定向到目的系統(tǒng)中的硬件上來;3.可執(zhí)行映象文件的存儲器映射必
2、須根據(jù)目的硬件的存儲器分布進展裁剪;4.在主程序執(zhí)行前,嵌入式應用程序必須先完成系統(tǒng)的初始化。一個完好的初始化包括用戶的啟動執(zhí)行代碼和ADS中C庫函數(shù)的初始化過程。圖1 Semihosting的實現(xiàn)舉個例子圖2 C語言庫函數(shù)構造圖3缺省的存儲器映射圖4連接器布局規(guī)那么缺省的工程工程設置剛開場一個嵌入式應用軟件開發(fā)時,ADS用戶可能并不完全清楚目的硬件的一些參數(shù)指標。比方有關外設、存儲器地址分布,甚至處理器類型等一些細節(jié),可能還沒有最終確定。為了在所有這些細節(jié)全部就緒前就能進展軟件開發(fā),ADS工具有一套程序構建和調(diào)試的缺省設置。理解這套缺省的工程工程設置方法,對于把握最終的移植步驟非常有好處。A
3、DS1.2 C語言函數(shù)庫Semihosting在ADS的C語言函數(shù)庫中,某些ANSIC的功能是由主機的調(diào)試環(huán)境來提供的,這套機制有一個專門術語叫Semihosting。Semihosting通過一組軟件中斷SWI指令來實現(xiàn)。如圖1所示,當一個Semihosting軟中斷被執(zhí)行時,調(diào)試系統(tǒng)先識別這個SWI懇求,然后掛起正在運行的程序,調(diào)用Semihosting的效勞,完成后再恢復原來的程序執(zhí)行。因此,主機執(zhí)行的任務對于程序來說是透明的。C語言庫函數(shù)構造從概念上來講,C語言庫函數(shù)可以被分成兩部分,一是ANSIC語言標準本身的一部分,一是只受某一特定ANSIC層次支持的函數(shù),如圖2所示。其中一些AN
4、SIC的功能是由主機調(diào)試環(huán)境調(diào)用驅動程序級的函數(shù)完成的。例如,ADS的庫函數(shù)printf把輸出信息輸出到調(diào)試器的控制臺窗口,這個功能通過調(diào)用_sys_write實現(xiàn),_sys_write執(zhí)行了一個把字符串輸出到主機控制臺的Semihosting軟中斷效勞程序。缺省的存儲器映射假設用戶在程序編譯時沒有指定映象的存儲器映射分布,ADS將為生成的目的代碼和數(shù)據(jù)分配一個缺省的存儲器映射圖,如圖3所示。目的印象被連接至地址0x8000,存儲和執(zhí)行區(qū)域都位于該地址開場的空間。RO只讀部分放在前面,接著是RW讀寫部分,最后是ZI零初始化部分。在ZI部分之上緊跟著HEAP,所以HEAP確實切地址要在連接時才能
5、確定。STACK的基地址是在應用程序啟動時由一個Semihosting操作提供。這項Semihosting操作返回的地址值視不同調(diào)試環(huán)境而定:ARMulator返回配置文件peripherals.ami中的設置值;缺省為0x 08000000。Multi-ICE返回的是調(diào)試器內(nèi)部變量$top_of_memory的值;缺省為0x 00080000。連接器布局規(guī)那么連接器對代碼和數(shù)據(jù)在存儲器系統(tǒng)中的分配,遵循一套規(guī)那么,如圖4所示。映象首先按照屬性以RO-RW-ZI的次序進展排列,在同一種屬性里面代碼先于數(shù)據(jù)。然后連接器將輸入段根據(jù)名字的字母順序進展排列,輸入段的名字與匯編代碼里面的塊名字指示一致
6、在匯編程序中用AREA要害字。在輸入段中,來自不同對象的代碼和數(shù)據(jù)放置次序與在連接器命令行中指定的對象文件次序一致。在需要靈敏分配代碼和數(shù)據(jù)放置位置的情況下,建議用戶不要簡單地依靠這些規(guī)那么。后面會介紹一種怎么控制代碼和數(shù)據(jù)布局的機制Scatterloading。圖5缺省的ADS初始化過程圖6 C庫函數(shù)重定向圖7 scatter文件語法圖8分散加載的簡單樣例啟動應用程序大多數(shù)嵌入式系統(tǒng)在進入應用主程序之前有一個初始化的過程,該過程完成系統(tǒng)的啟動和初始化功能。缺省的ADS初始化過程如圖5所示??傮w上,初始化過程可以分成兩部分來看:_main負責設置運行映像存儲器映射;_rt_entry負責庫函數(shù)
7、的初始化。_main完成代碼和數(shù)據(jù)的復制,并把ZI數(shù)據(jù)區(qū)清零。這一步只有當代碼和數(shù)據(jù)區(qū)在存儲和運行時處于不同的存儲器位置時才有意義。接著_main跳進_rt_entry,進展STACK和HEAP等的初始化。最后_rt_entry跳進應用程序的入口main。當應用程序執(zhí)行完時,_rt_entry又將控制權交還給調(diào)試器。函數(shù)main在ADS中有非凡的意義。當一個程序工程工程中存在main時,連接器會把_main和_rt_entry中的初始化代碼連接進來;假設沒有main函數(shù),初始化過程就不會被連接,結果就會導致一些標準的C庫函數(shù)無效。根據(jù)目的環(huán)境裁減C庫函數(shù)缺省狀態(tài)下C庫函數(shù)利用Semihotst
8、ing機制來實現(xiàn)設備驅動的功能。但一個真正的嵌入式系統(tǒng),要使用到詳細的外設或硬件獨立于主機環(huán)境運行。C庫函數(shù)重定向用戶可以定義自己的C語言庫函數(shù),連接器在連接時自動使用這些新的功能函數(shù)。這個過程叫做重定向C語言庫函數(shù),如圖6所示。舉個例子來說,用戶有一個I/O設備如UART。本來庫函數(shù)fputc是把字符輸出到調(diào)試器控制窗口中去的,但用戶把輸出設備改成了UART端口,這樣一來,所有基于fputc函數(shù)的printf系列函數(shù)輸出都被重定向到UART端口上去了。下面是實現(xiàn)fputc重定向的一個例子:externvoidsendcharchar*ch;intfputcintch,FILE*fcharte
9、mpch=ch;sendchar&tempch;returnch;這個例子簡單地將輸入字符重新定向到另一個函數(shù)sendchar,sendchar假定是一個另外定義的串口輸出函數(shù)。在這個地方,fputc就似乎目的硬件和標準C庫函數(shù)之間的一個抽象層。在C語言庫函數(shù)中禁用Semihosting在一個獨立的嵌入式應用程序中,應當不存在SemihostingSWI操作。因此,用戶必須確定在所有調(diào)用到的庫函數(shù)中沒有使用Semihosting。為了保證這一點,在程序中可以引進一個符號要害字_use_no_semihosting:在C代碼中,使用#prgrama#pragmaimport_use_no
10、_semihosting_swi在匯編程序中,使用IMPORT IMPORT_use_no_semihosting_swi這樣,當有使用SWI機制的庫函數(shù)被連接時,連接器會進展報錯:Error:Symbol_semihosting_swi_guardmultiplydefined為了確定詳細是哪一個函數(shù),連接時翻開-verbose選項。這樣在結果信息輸出時,該庫函數(shù)上將有一個_I_use_semihosting_swi的標記。Loadingmembersys_wxit.ofromc_a_un.1.Definition:_sys_exit Reference:_I_use_semihosting
11、_swi用戶必需要把這些函數(shù)定義成自己的執(zhí)行內(nèi)容。有一點需要注重,連接器只能報告庫函數(shù)中被調(diào)用的Semihosting,對用戶自定義函數(shù)中使用的Semihosting那么不會報錯。根據(jù)目的硬件定制存儲器映射分散裝載Scatlerloading在實際的嵌入式系統(tǒng)中,ADS提供的缺省存儲器映射是不能滿足要求的。用戶的目的硬件通常有多個存儲器設備位于不同的位置,并且這些存儲器設備在程序裝載和運行時可能還有不同的配置。Scattertoading可以通過一個文本文件來指定一段代碼或數(shù)據(jù)在加載和運行時在存儲器中的不同位置。這個文本文件scatterfile在命令行中由-scatter開關指定,例如:ar
12、mlink_scatterscat.scffilel.ofile2.0在scatterfile中可以為每一個代碼或數(shù)據(jù)區(qū)在裝載和執(zhí)行時指定不同的存儲區(qū)域地址,Scatlertoading的存儲區(qū)塊可以分成二種類型:裝載區(qū):當系統(tǒng)啟動或加載時應用程序的存放區(qū)。執(zhí)行區(qū):系統(tǒng)啟動后,應用程序進展執(zhí)行和數(shù)據(jù)訪問的存儲器區(qū)域,系統(tǒng)在實時運行時可以有一個或多個執(zhí)行塊。映像中所有的代碼和數(shù)據(jù)都有一個裝載地址和運行地址二者可能一樣也可能不同,視詳細情況而定。在系統(tǒng)啟動時,C函數(shù)庫中的_main初始化代碼會執(zhí)行必要的復制及清零操作,使應用程序的相應代碼和數(shù)據(jù)段從裝載狀態(tài)轉入執(zhí)行狀態(tài)。1.scatter文件語法s
13、catter文件是一個簡單的文本文件,包含一些簡單的語法。My_Region0x00000x1000thecontextofregion每個塊由一個頭標題開場定義,頭中至少包含塊的名字和起始地址,另外還有最大長度和其他一些屬性選項。塊定義的內(nèi)容包括在緊接的一對花括號內(nèi),依靠于詳細的系統(tǒng)情況。一個加載塊必須至少含有一個執(zhí)行塊;理論中通常有多個執(zhí)行塊。一個執(zhí)行塊必須至少含有一個代碼或數(shù)據(jù)段;這些通常來自源文件或庫函數(shù)等的目的文件;通配符號*可以匹配指定屬性項中所有沒有在文件中定義的余下部分。2.簡單分散加載樣例圖8所示樣例中,只有一個加載塊,包含了所有的代碼和數(shù)據(jù),起始地址為0。這個加載塊一共對應
14、兩個執(zhí)行塊。一個包含所有的RO代碼和數(shù)據(jù),執(zhí)行地址與裝載地址一樣;同時另一個起始地址為0x10000的執(zhí)行塊,包含所有的RW和ZI數(shù)據(jù)。這樣當系統(tǒng)開場啟動時,從第一個執(zhí)行塊開場運行執(zhí)行地址等于裝載地址,在執(zhí)行過程中,有一段初始化代碼會把裝載塊中的一部分代碼轉移到另外的執(zhí)行塊中。下面是這個scatter描繪文件,該文件描繪了上述存儲器映射方式。LOAD_ROM0x4000EXE_ROM0x00000x4000;Rootregion*+RO;AllcodeandconstantdataRAM0x 100000x8000*+RW,+ZI;Allnon-constantdata3.在分散文件中放置對象
15、在大多數(shù)應用中,并不是像前例那樣,簡單地把所有屬性都放在一起,用戶需要控制特定代碼和數(shù)據(jù)段的放置位置。這可以通過在scatter文件中對單個目的文件進展定義實現(xiàn),而不是只簡單地依靠通配符。為了覆蓋標準的連接器布局規(guī)那么,我們可以使用+FIRST和+LAST分散加載指令。典型的例子是在執(zhí)行塊的開場處放置中斷向量表格:LOAD_ROM0x00000x4000EXEC_ROM0x00000x4000vectors.oVect,+FIRST*+RO;moreexecregions.在這個scatter文件中,保證了vextors.o中的Vect域被放置于地址0x0000。4.RootRegion根區(qū)根
16、區(qū)是一個執(zhí)行塊,它的加載地址與執(zhí)行地址是一致的。每個scatter文件至少有一個根區(qū)。分散加載有一個限制:創(chuàng)立執(zhí)行塊的代碼和數(shù)據(jù)即完成復制和清零的代碼和數(shù)據(jù)無法自行復制到另一個位置。因此,在根區(qū)中必須含有下面的部分:_main.o,包含復制代碼/數(shù)據(jù)的代碼;連接器輸出變量$Table和ZISection$Table,包含被復制代碼/數(shù)據(jù)的地址。由于上面兩個部分的屬性是只讀的,因此他們被*+RO通配符語法匹配。假設*+RO被用在了非根區(qū)中,那么在根區(qū)中必須顯式地指明另一個RO區(qū)域。下面是一個例子:LOAD_ROM0x00000x4000EXE_ROM0x00000x4000;rootregion
17、_main.o+RO;copyingcode*Region$Tabl0e;RO/RWaddressestocopy*ZISection$Table;ZIaddressestozeroRAM0x 100000x8000*+RO;allotherROsections*+RW,+ZI;allRWandZIsections放置堆棧和heap Scatterloading機制提供了一種指定代碼和靜態(tài)數(shù)據(jù)布局的方法。下面介紹怎么放置應用程序的堆棧和heap。*_user_initial_stackheap重定向應用程序的堆棧和heap是在C庫函數(shù)初始化過程中建立起來的。可以通過重定向對應的子程序來改變堆棧
18、和heap的位置,在ADS的庫函數(shù)中,即_user_initial_stackheap函數(shù)。_user_initial_stackheap可以用C或匯編來實現(xiàn),它必須返回如下參數(shù):r0:heap基地址;r1:堆?;刂罚籸2:heap長度限制值需要的話;r3:堆棧長度限制值。當用戶使用分散裝載功能的時候,必須重調(diào)用_user_initial_stackheap,要不然連接器會報錯:Error:L6218E:Undefined symbol Image$ZI$Limitreferred from sys_stackheap.o*存儲器模型ADS提供了兩種實時存儲器模型。缺省時為one-regio
19、n,應用程序的堆棧和heap位于同一個存儲器區(qū)塊,使用的時候相向生長,當在heap區(qū)分配一塊存儲器空間時需要檢查堆棧指針。另一種情況是堆棧和heap使用兩塊獨立的存儲器區(qū)域。對于速度非凡快的RAM,可選擇只用來作堆棧使用。為了使用這種two-region模型,用戶需要導入符號use_two_region_memory,heap使用需要檢查heap的長度限制值。對這兩種模型來說,缺省情況下對堆棧的生長都不進展檢查。用戶可以在程序編譯時使用-apcs/swst編譯器選項來進展軟件堆棧檢查。假設使用two-region模型,必須得在執(zhí)行_user_initial_stackheap時指定一個堆棧限制
20、值。圖9重定向_user_initial_stackheap圖10根底初始化過程圖11 ROM/RAM重定向和映射表1系統(tǒng)復位和初始化目前情況,一般假設程序從C庫函數(shù)的初始化入口_main開場執(zhí)行。實際上,所有的嵌入式程序在啟動時都要執(zhí)行一些系統(tǒng)級的初始化操作。在此討論這方面的內(nèi)容。初始化過程圖10中顯示了一個基于ARM的嵌入式系統(tǒng)的根底初始化過程??梢钥吹?,在_main之前參加了一個復位處理模塊reset handler,它在系統(tǒng)上電復位時立即啟動。標識為$sub$main的新代碼塊在進入主程序之前執(zhí)行。復位處理模塊reset handler通常是一小段匯編代碼,在系統(tǒng)復位時執(zhí)行。它至少完成
21、應用程序中使用到的所有處理器形式的堆棧初始化工作。對于含有本地存儲器系統(tǒng)的內(nèi)核比方含cache的ARM內(nèi)核,配置工作也必須在這一段初始化過程中完成。當完成系統(tǒng)初始化之后,通常程序會跳向_main,開場C庫函數(shù)的初始化過程。系統(tǒng)初始化過程一般還包括另外一些內(nèi)容,中斷使能等,這些大多安排在C庫函數(shù)的初始化完成之后執(zhí)行。$sub$main完成這部分功能。向量表vector table所有的ARM系統(tǒng)都有一張中斷向量表當出現(xiàn)異常需要處理時,必須調(diào)用向量表。向量表一般要位于0地址處。表2表3表4表5表6表7表8表9表10存儲器配置*ROM/RAM重定向當系統(tǒng)啟動的時候,為了保證0地址處有正確的啟動代碼存
22、在,需要非易失性的存儲器。一種簡單的方法,就是把系統(tǒng)0x0000開場的一塊地址分配給ROM。其缺點是,由于ROM的訪問速度比RAM慢很多,當執(zhí)行中斷響應需要從中斷向量表跳轉時,會給系統(tǒng)性能帶來損失;同時,在ROM中的向量表內(nèi)容也不能被用戶程序動態(tài)修改。另外一種可行的方案如圖11所示。ROM位于地址0x1000開場的地方,但是在系統(tǒng)復位時又被存儲器控制器映射到0x0000地址處。這樣當系統(tǒng)啟動之后,在地址0x0000看到的是ROM,系統(tǒng)執(zhí)行這塊ROM中的啟動代碼,啟動代碼跳轉到真正的ROM的地址,并讓存儲器控制器移除對ROM的地址映射。這時0x0000地址處的存儲器又恢復回了RAM。_main中
23、的代碼把向量表copy到0x0000處的RAM中去,使得異常時能被正確響應。表1為ARM匯編中執(zhí)行ROM/RAM重定向和映射的一個例子。它以ARM公司的Integrator平臺為根底的,該方法適用于類似ROM/RAM重定向方法的所有平臺。第一條指令完成從ROM的映射地址0x00000到真實地址的跳轉。地址標號instrUCt_2是ROM的真實地址0x 180004。然后通過設置Integrator平臺上的相應控制存放器,移除ROM的地址映射。代碼在系統(tǒng)一啟動就被執(zhí)行。所有關于地址重定向/映射的操作必須在C庫函數(shù)初始化之前完成。*本地存儲器配置許多ARM處理器都有片上存儲器系統(tǒng),如cache和嚴
24、密耦合存儲器TCM、存儲器治理單元MMU或存儲器保護單元MPU。這些設備都要在系統(tǒng)初始化過程中正確配置,并且有一些非凡的要求需要考慮。由前文可知,_main中的C庫函數(shù)初始化代碼負責程序運行時的存儲器系統(tǒng)設置。因此,整個存儲器系統(tǒng)本身必須得在_main之前完成初始化工作,如MMU或MPU必須在reset handler里面完成配置。嚴密耦合存儲器TCM的初始化同樣須在_main之前完成通常在MMU/MPU之前,因為一般程序都需要把代碼和數(shù)據(jù)分散裝入TCM。需要注重的是當TCM被使能后,不再訪問被TCM屏蔽的存儲器。關于cache的一致性問題,假設cache在_main之前使能的話,那么當_ma
25、in里面進展從裝載區(qū)到執(zhí)行區(qū)的代碼和數(shù)據(jù)拷貝時因為在拷貝過程中指令和數(shù)據(jù)在本質上都是被當作數(shù)據(jù)處理,指令會出如今數(shù)據(jù)緩沖區(qū)。防止此問題的方法是在C庫函數(shù)初始化完成后再使能cache。*Scatter loading與存儲器配置不管是通過ROM/RAM重定向還是MMU配置的方法,假設系統(tǒng)在啟動和運行時存儲器分布不一致,scatterloading文件中的定義就要按照系統(tǒng)重定向后的存儲器分布情況進展。以上文ROM/RAM重定向為例:LOAD_ROM 0x10000 0x8000EXE_ROM 0x10000 0x8000reset_handler.o+RO,+FIRST.RAM 0x0000 0x
26、4000vectors.o+RO,+FIRST.裝載區(qū)LOAD_ROM被放置在0x10000處,代表了重定向之后代碼和數(shù)據(jù)的裝載地址。堆棧的初始化程序中可能用到的處理器形式,都需要定義一個堆棧指針。在表2中,堆棧位于stack_base標識的地址中。這個符號可以是存儲器系統(tǒng)中的一個直接地址,也可以在另外的匯編文件中定義,由scatter文件來定義分配地址。表2代碼為FIQ和IRQ形式各分配了一個256字節(jié)的堆棧,用戶可以用同樣的方法為其他形式也分配堆棧。最簡單的方法就是進入相應的形式,然后為SP存放器指定相應的值。假設想使用軟件堆棧檢查,還必須指定一個堆棧長度限制值。堆棧指針和堆棧限制的數(shù)值會
27、作為參數(shù)自動傳遞到C庫函數(shù)的初始化代碼_user_initial_stackheap中,在_user_initial_stackheap中不應當修改這些值。硬件初始化$sub$main一般來說,應當把所有的系統(tǒng)初始化代碼與主應用程序別分開來,但是有幾個例外,比方cache和中斷的使能,需要在C庫函數(shù)初始化之后執(zhí)行。表3代碼顯示了怎么使用$sub和$supper。連接器把呼叫main的函數(shù)交換成呼叫$sub$main,完成cache和中斷的使能,并最終跳向main。執(zhí)行形式考慮為主應用程序選擇一個處理器執(zhí)行形式非常重要,這取決于系統(tǒng)的初始化代碼。許多在啟動過程中使用到的功能,如MMU/MPU的配
28、置、中斷的使能等,只能在特權級形式下進展。假設需要在特權極形式下運行自己的應用程序,只要在退出初始化過程之前改變到相應的形式就行了,沒有其他任何問題。假設使用user形式,必須保證所有只能在特權形式下執(zhí)行的功能完成之后,才能進入user形式。因為system形式和user形式使用一樣的存放器組,reset handler應當從system形式退出,_user_initial_stackheap在system形式下完成應用程序堆棧的初始化。這樣在處理器進入user形式后,所有的堆??臻g都已經(jīng)被正確設置好了。對存儲器布局的進一步考慮在scatter文件中分配硬件地址雖然可以在一個scatter文件
29、中描繪代碼和數(shù)據(jù)的分分布局,但是目的硬件中的外設存放器,堆棧和heap配置仍然直接采用硬件地址在程序源代碼中進展設置。假設把所有存儲器地址相關的信息都在scatter文件中進展定義,防止在源文件中引用絕對硬件地址,對程序的工程化治理是有大好處的。*在scatter文件中定義目的外設地址通常外設存放器的地址在程序文件或頭文件中定義,也可以聲明一個構造類型指向外設存放器,構造的地址定位在scatter文件中完成。舉個例子來說,目的定時器上有2個32位的存放器,可以用表4來映射這些存放器。為了把構造放置在指定的存儲器地址上面,創(chuàng)立一個新的執(zhí)行區(qū)見表5。scatter文件便把timer_regs構造定位在了地址0x 40000000。注重,在啟動過程當中這些存放
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度新能源電動汽車充電樁安裝承包合同4篇
- 2025年度磚廠設備更新與承包合同4篇
- 二零二五年度高校講師聘請合同(含教學與科研)2篇
- 二零二五版場地綠化調(diào)查與規(guī)劃服務合同模板3篇
- 2025版民辦醫(yī)療機構設備采購與維修服務合同4篇
- 二零二五版過敏性疾病患者個性化治療方案合同3篇
- 2024預包裝食品倉儲物流服務外包合同范本2篇
- 食堂就餐環(huán)境優(yōu)化合同(2025年度)3篇
- 2025年度交通運輸履約保函服務標準3篇
- 二零二五年度二零二五智能城市建設項目合作協(xié)議4篇
- 天津市武清區(qū)2024-2025學年八年級(上)期末物理試卷(含解析)
- 《徐霞客傳正版》課件
- 江西硅博化工有限公司年產(chǎn)5000噸硅樹脂項目環(huán)境影響評價
- 高端民用航空復材智能制造交付中心項目環(huán)評資料環(huán)境影響
- 量子醫(yī)學成像學行業(yè)研究報告
- DB22T 3268-2021 糧食收儲企業(yè)安全生產(chǎn)標準化評定規(guī)范
- 辦事居間協(xié)議合同范例
- 正念減壓療法詳解課件
- GB 30254-2024高壓三相籠型異步電動機能效限定值及能效等級
- 重大事故隱患判定標準與相關事故案例培訓課件
- 藥物制劑工(三級)理論試題題庫及答案
評論
0/150
提交評論