日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Zynq的AMP开发注意事项之sdk_repo

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Zynq的AMP开发注意事项之sdk_repo 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

前言

1.BSP工程說明

第一步:創建BSP工程,選擇硬件平臺、cpu核和支持的OS

第二步:BSP工程設置

(1)版本+庫文件選擇

(2)standalone配置

(3)drivers支持

(4)編譯選項

2.sdk_repo的作用

(1)STDOUT_REDIR 宏定義

(2)boot.S

(2.1)CPU1內存分配(必須)

(2.2)啟動地址重映射:_boot(非必須)

(2.3)AMP模式禁用L2 cache(必須)

(3)asm_vectors.S(非必須)

(4)xtime_l.c修改(必須)

3.總結歸納

4.附錄




前言

前面一篇文章基本上講解了Zynq的AMP模式的開發流程,需要結合Vivado、SDK和Petalinux三個軟件。在開發過程中還需要注意一些問題:sdk_repo的使用、設備樹的定義、uboot啟動參數、內核映像文件類型等等,這里首先說明sdk_repo的使用問題。


首先,在SDK中開發用戶應用程序時,需要有2個工程文件:用戶應用程序工程+BSP工程。

其中,BSP工程為應用程序工程提供板級支持,BSP工程中封裝了板卡所有底層硬件的原理描述和函數操作,用戶不需要詳細了解板卡底層的設計原理,只需要直接使用BSP提供的API接口函數即可對硬件進行相應操作。

版本說明:

本人安裝的開發軟件均是2017.4版本,軟件自帶的sdk源碼版本為:standalone_v6_5;

官方資料xapp1078_2014.04下載中,提供的sdk_repo源碼版本為:standalone_v4_299;



1.BSP工程說明

注意:這里并沒有將BSP配置成AMP模式,只是簡單介紹BSP工程的創建流程。


第一步:創建BSP工程,選擇硬件平臺、cpu核和支持的OS

第二步:BSP工程設置

(1)版本+庫文件選擇

在安裝SDK軟件時,standalone文件自動包含在安裝包中,默認的版本已確定,除非使用用戶的standalone。

庫文件可以根據用戶需要自行選擇,如openamp庫。

(2)standalone配置

主要是需要配置系統所使用的輸入輸出接口:一般選擇uart0或uart1。

zynq_fsbl_bsp:當創建fsbl工程時的bsp工程師,才會選擇有效。

(3)drivers支持

以下顯示是bsp提供的驅動支持,用于應用程序對底層硬件的訪問和操作。

(4)編譯選項

程序從創建到生產可執行文件需要歷經:預處理、編譯、匯編、連接。

archiver:linux系統下交叉編譯工具中的庫管理器。

compiler:linux系統下交叉編譯工具中的集成編譯工具。

compiler flag:gcc編譯標志

extra?compiler flag:gcc附加編譯標志

歸納:由創建到生成BSP工程的過程中,用戶需要根據自己的使用要求進行合理修改,前提是需要理解配置選項的具體作用。


2.sdk_repo的作用

在基于官方文檔:《xapp1078-amp-linux-bare-metal.pdf》進行AMP模式開發中,必須要使用到官方提供的sdk_repo文件。針對AMP模式,sdk_repo中對一些啟動文件進行了必要的修改,下面進行詳細說明:

修改設計內容:(參考1078官方資料下的《Vivado instructions.txt》)

standalone BSP.Note: The standalone v4.2 BSP was modified as follows:?- armcc/_sys_write.c, gcc/write.c, printc, xil_printf.c: These changes add a new define 'STDOUT_REDIR'that prevents the removal of calls to outbyte() if STDOUT_BASEADDRESS is not defined- armcc/boot.S, gcc/boot.S: These changes remove remapping of virtual address 0x20000000 to physicaladdress 0x00000000, configures address 0x00000000-0x2fffffff to be unavailable, and disables sharingand L2 cache on address 0x30000000-0x3fffffff. The startup code was also modified to allow redirectingcpu0 or cpu1 to a different starting address (This redirecting ability is not used for xapp1078).- xtime_l.c: The change to this file prevents re-initializing the global timer.- asm_vectors.S: Two extra vectors are added at the end of the vector table and are used by the boot.Sredirecting code. (This redirecting ability is not used for xapp1078).

(1)STDOUT_REDIR 宏定義

在armcc/_sys_write.c, gcc/write.c, printc, xil_printf.c中,所有涉及到print打印函數的地方,都增加了對應的宏定義,如:

#if defined STDOUT_BASEADDRESS || STDOUT_REDIRoutbyte( *lp++); #endif

原因:1078提供的AMP設計中,雙核通信過程:cpu1會通過xil_printf()函數將打印消息發送給cpu0,cpu0再通過系統uart1將打印消息發送給顯示器。

在1078的bsp設置中,Select Overview->standalone and change stdin and stdout to None,沒有定義輸入輸出端設備,即沒有STDOUT_BASEADDRESS 宏。為了避免xil_printf()無效,才有了STDOUT_REDIR 宏定義。

(我的配置:在vivado中使能uart0:使用EMIO引腳,使能uart1:使用ps側標準IO;在cpu1的bsp配置中使用uart0;

因此,不需要定義STDOUT_REDIR,demo也可以正常運行)


(2)boot.S

(2.1)CPU1內存分配(必須)

作用:限定cpu1的裸機程序不可訪問低內存空間(保留給linux系統專用)

第一:將虛擬地址0x20000000重新映射到物理地址0x00000000 部分的代碼注釋(注意:sdk軟件自帶的standalone不會有這段代碼,可忽略此步,這段代碼可能是xilinx以前增加的

第二:將地址0x00000000-0x2fffffff(768M)配置為不可用。注意:這里配置的DDR是1G,因此cpu1運行裸機程序的情況下,配置低768M給cpu0使用,cpu1只是用高256M。如果DDR是512M,分為模式應該是:384M+128M。

第三:設置0x30000000-0x3fffffff僅作為CPU1的內部使用。如果DDR是512M,因該是高128M。

注意:關于MMU的原理和相關描述符的具體含義請參考《?嵌入式系統Linux內核開發實戰指南ARM平臺.pdf》中的第4章節(這里講的描述符可能不是arm最新架構的,比如沒有標志位s,此時參考下文:MMU配置和使用)

//第一步:注釋代碼 // /* In case of AMP, map virtual address 0x20000000 to 0x00000000 and mark it as non-cacheable */ //#if USE_AMP==1 // ldr r3, =0x1ff /* 512 entries to cover 512MB DDR */ // ldr r0, =TblBase /* MMU Table address in memory */ // add r0, r0, #0x800 /* Address of entry in MMU table, for 0x20000000 */ // ldr r2, =0x0c02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ //mmu_loop: // str r2, [r0] /* write the entry to MMU table */ // add r0, r0, #0x4 /* next entry in the table */ // add r2, r2, #0x100000 /* next section */ // subs r3, r3, #1 // bge mmu_loop /* loop till 512MB is covered */ //#endif/* In case of AMP, mark address 0x00000000 - 0x2fffffff DDR as unassigned/reserved *//* and address 0x30000000 - 0x3fffffff DDR as inner cached only */#if USE_AMP==1//第二步:保留低768M(如果DDR是512M,可將768M修改為384M,cpu0也可以正常運行系統)ldr r3, =0x2ff /* 768 entries to cover 768MB DDR */ldr r0, =TblBase /* MMU Table address in memory */ldr r2, =0x0000 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ mmu_loop:str r2, [r0] /* write the entry to MMU table */add r0, r0, #0x4 /* next entry in the table */add r2, r2, #0x100000 /* next section */subs r3, r3, #1bge mmu_loop /* loop till 768MB is covered *///第三步:設置高256M專為CPU1使用(如果DDR是512M,這里的256M需修改為128M)ldr r3, =0x0ff /* 256 entries to cover 256MB DDR */movw r2, #0x4de6 /* S=b0 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b1 *///注意:CB為01:表示cpu1的MMU設置為了分段地址管理,不支持cache但支持buffer;mmu域是15;保護標志位為0;訪問權限為11:可讀可寫;在ARMv5以上版本處理器中有定義,如果TEX等于1,表示系統支持寫時分配cache,這里沒有分配cache;s為0:表示此內存不共享!movt r2, #0x3000 /* S=b0, Section start for address 0x30000000 */ mmu_loop1:str r2, [r0] /* write the entry to MMU table */add r0, r0, #0x4 /* next entry in the table */add r2, r2, #0x100000 /* next section */subs r3, r3, #1bge mmu_loop1 /* loop till 256MB is covered */ #endif

(2.2)啟動地址重映射:_boot(非必須)

(注意:這個功能在1078上用不上,可不增加這一段)

... ... .globl _cpu0_catch .globl _cpu1_catch .globl OKToRun .globl EndlessLoop0 ... ..._boot: //復位中斷向量,系統復位后代碼從這里啟動/* Test which processor is running and jump to the catch address */mrc p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #0bne NotCpu0 //如果不是cpu0,則跳轉到NotCpu0處繼續判斷ldr r0, =_cpu0_catch //如果是CPU0,則準備跳轉到_cpu0_catch處b cpuxCont NotCpu0: //如果不是cpu0cmp r1, #1 bne EndlessLoop0 //如果也不是cpu1,則跳轉到endlessloop0ldr r0, =_cpu1_catch //如果是cpu1,則準備跳轉到_cpu1_catch處b cpuxCont EndlessLoop0:wfe //等待喚醒信號b EndlessLoop0 /* Jump to address pointed to by cpux_catch */ cpuxCont:ldr lr, [r0]bx lr //執行跳轉OKToRun:mrc p15, 0, r0, c0, c0, 0 /* Get the revision */and r5, r0, #0x00f00000 and r6, r0, #0x0000000forr r6, r6, r5, lsr #20-4 ... ...

但是,standalone_v6_5中也有類似的一段,如下:

作用:從下面的匯編來看,如果實際加載中測到的CPU_ID和配置的CPU_ID如果不同,BSP將無法啟動。

...... .set SLCRCPURSTReg, (0xF8000000 + 0x244) /*(XPS_SYS_CTRL_BASEADDR + A9_CPU_RST_CTRL_OFFSET)*/ .set EFUSEStaus, (0xF800D000 + 0x10) /*(XPS_EFUSE_BASEADDR + EFUSE_STATUS_OFFSET)*/ ......_prestart: _boot:#if XPAR_CPU_ID==0 //如果bsp中設置的是CPU0,則只有cpu0會啟動,cpu1無法啟動!/* only allow cpu0 through */mrc p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #0beq CheckEFUSEEndlessLoop0:wfeb EndlessLoop0CheckEFUSE:ldr r0,=EFUSEStausldr r1,[r0] /* Read eFuse setting */ands r1,r1,#0x80 /* Check whether device is having single core */beq OKToRun/* single core device, reset cpu1 */ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */ldr r1,=SLCRUnlockKey /* set unlock key */str r1, [r0] /* Unlock SLCR */ldr r0,=SLCRCPURSTRegldr r1,[r0] /* Read CPU Software Reset Control register */orr r1,r1,#0x22str r1,[r0] /* Reset CPU1 */ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */ldr r1,=SLCRlockKey /* set lock key */str r1, [r0] /* lock SLCR */#elif XPAR_CPU_ID==1 //如果bsp中設置的是CPU1,則只有cpu1會啟動,cpu0無法啟動!/* only allow cpu1 through */mrc p15,0,r1,c0,c0,5and r1, r1, #0xfcmp r1, #1beq CheckEFUSE1b EndlessLoop1CheckEFUSE1:ldr r0,=EFUSEStausldr r1,[r0] /* Read eFuse setting */ands r1,r1,#0x80 /* Check whether device is having single core */beq OKToRunEndlessLoop1:wfeb EndlessLoop1 #endif

(2.3)AMP模式禁用L2 cache(必須)

作用:如果是AMP模式,cpu1就需要禁用L2 cache;(這段代碼兩個sdk源碼均有,不需要用戶添加)

原因參考《Zynq的AMP開發注意事項之禁用L2 cache》

/* For AMP, assume running on CPU1. Don't initialize L2 Cache (up to Linux) */ #if USE_AMP!=1ldr r0,=L2CCCrtl /* Load L2CC base address base + control register */mov r1, #0 /* force the disable bit */str r1, [r0] /* disable the L2 Caches */ldr r0,=L2CCAuxCrtl /* Load L2CC base address base + Aux control register */ldr r1,[r0] /* read the register */ldr r2,=L2CCAuxControl /* set the default bits */orr r1,r1,r2str r1, [r0] /* store the Aux Control Register */ldr r0,=L2CCTAGLatReg /* Load L2CC base address base + TAG Latency address */ldr r1,=L2CCTAGLatency /* set the latencies for the TAG*/str r1, [r0] /* store the TAG Latency register Register */ldr r0,=L2CCDataLatReg /* Load L2CC base address base + Data Latency address */ldr r1,=L2CCDataLatency /* set the latencies for the Data*/str r1, [r0] /* store the Data Latency register Register */ldr r0,=L2CCWay /* Load L2CC base address base + way register*/ldr r2, =0xFFFFstr r2, [r0] /* force invalidate */ldr r0,=L2CCSync /* need to poll 0x730, PSS_L2CC_CACHE_SYNC_OFFSET *//* Load L2CC base address base + sync register*/ ......

(3)asm_vectors.S(非必須)

在向量表的末尾添加了兩個額外的向量,由boot.s中的重定向代碼使用。

.globl _boot .globl _vector_table .globl _cpu0_catch .globl _cpu1_catch .globl OKToRun .globl EndlessLoop0.globl FIQInterrupt .globl IRQInterrupt .globl SWInterrupt .globl DataAbortInterrupt .globl PrefetchAbortInterrupt.globl IRQHandler .globl prof_pc.section .vectors _vector_table:B _bootB UndefinedB SVCHandlerB PrefetchAbortHandlerB DataAbortHandlerNOP /* Placeholder for address exception vector*/B IRQHandlerB FIQHandler#if XPAR_CPU_ID==0 //如果bsp中設置的是CPU0 _cpu0_catch: //則:cpu0可以運行 .word OKToRun /* fixed addr for caught cpu- */ _cpu1_catch: //cpu1會跳轉到等待wfe循環中 .word EndlessLoop0 /* fixed addr for caught cpu- */#elif XPAR_CPU_ID==1 //如果bsp中設置的是cpu1,則cpu啟動與上述相反 _cpu0_catch: .word EndlessLoop0 _cpu1_catch: .word OKToRun #endifIRQHandler: /* IRQ vector handler */stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code*/ #ifdef __ARM_NEON__vpush {d0-d7}vpush {d16-d31}vmrs r1, FPSCRpush {r1}vmrs r1, FPEXCpush {r1} #endif......

?


(4)xtime_l.c修改(必須)

作用:在AMP模式下,global全局定時器肯定會在CPU0的系統中完成初始化,因此避免CPU1啟動或是運行過程中CPU1重啟時,將global全局定時器reset!

void XTime_SetTime(XTime Xtime) {#ifdef USE_AMPif(Xil_In32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET) && 0x1) {//Timer is already enabled so don't reset itreturn;} #endif/* Disable Global Timer */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET, 0x0);/* Updating Global Timer Counter Register */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET, (u32)Xtime);Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET,(u32)(Xtime>>32));/* Enable Global Timer */Xil_Out32(GLOBAL_TMR_BASEADDR + GTIMER_CONTROL_OFFSET, 0x1); }

3.總結歸納

(1)首先,1078文件中提供的sdk_repo并不是必須的,在經過理解之后,我們已經知道需要修改哪些必須的內容,并可以直接在standalone_v6_5源碼上進行修改,依然能夠完成AMP模式驗證。

(2)注意:如果需要使用standalone_v4_299,除了在新建BSP工程前導入sdk_repo外,還需要在BSP配置選項中:OS version——>4.2版本,默認是6.5(軟件自帶);但是使用4.2版本源碼會出現很多報錯的情況,因此需要用戶謹慎使用。

(3)本人建議:直接使用6.5版本,并在此基礎上進行相應修改。

有問題交流請聯系,qq:1030843709 泊葉

4.附錄

xilinx官網關于SDK的詳細使用介紹:

https://china.xilinx.com/search/site-keyword-search.html#q=sdk&firstQueryCause=omniboxFromLink&firstQueryMeta={%22partialQueries%22:%22%22%20,%20%22suggestionRanking%22:3%20,%20%22suggestions%22:%22zynq%207000%20qspi%3Bug1157%3Bug1144%3Bsdk%3Bcallbackref%22%20,%20%22partialQuery%22:%22undefined%22%20,%20%22JSUIVersion%22:%222.4382.16%3B2.4382.16%22}

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Zynq的AMP开发注意事项之sdk_repo的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。