大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是在i.MXRT1170上PXP對CM7 TCM進(jìn)行隨機地址短小數(shù)據(jù)寫入操作限制。
在 MCU 里能夠?qū)ζ瑑?nèi)外映射的存儲器進(jìn)行讀寫操作的主設(shè)備(Master)除了常見的 Core 以及 DMA 外,其實還有一些面向高速數(shù)據(jù)傳輸(比如 USB、uSDHC、ENET 接口等)或其他特定功能(比如 GPU、LCD、Crypto 等)的外設(shè),但就用戶數(shù)據(jù)搬移處理而言,一般我們只借助 Core 和 DMA。
在 i.MXRT 四位數(shù)上,還有一個叫 PXP 的外設(shè),這本是一個面向像素數(shù)據(jù)處理的模塊,但是它也能夠完成一般數(shù)據(jù)搬移處理任務(wù)。當(dāng)我們借助這個 PXP 來做數(shù)據(jù)搬移時,發(fā)現(xiàn)它在對 CM7 TCM 寫入時有一些使用限制。今天我們就來聊聊這個話題:
一、PXP功能簡介
先來看一下 PXP 模塊功能框圖,既然是面向圖像數(shù)據(jù)處理,那常見的圖像縮放、色彩空間轉(zhuǎn)換、圖像旋轉(zhuǎn)功能支持必不可少(即下圖藍(lán)框里的三個獨立引擎被整合在 PXP 里),這些操作實際上都涉及到 FrameBuffer 像素數(shù)據(jù)處理(讀改寫) 。
再進(jìn)一步細(xì)讀 PXP 特性,我們發(fā)現(xiàn)除了像素處理之外,它還是個標(biāo)準(zhǔn)的 2D DMA(這里 2D 的意思是為搬移二維圖像數(shù)據(jù)而設(shè)計的),這就是我們所要的數(shù)據(jù)搬移特性。在用 PXP 做數(shù)據(jù)搬移操作時,當(dāng)源 FrameBuffer 和目的 FrameBuffer 大小相同,且搬移目標(biāo)尺寸就是 FrameBuffer 長度時,其就蛻變成了大家所熟悉的普通 DMA。
二、一個RT1170的Errata
在我們實測 PXP 數(shù)據(jù)搬移功能時,我們先來看一個 RT1160/1170 上獨有的 Errata,也正是因為這個 Errata 讓痞子衡關(guān)注到了 PXP 的 2D DMA 功能。
這個 Errata 提及到 RT1160/1170 里若干個具有存儲器讀寫能力的主設(shè)備在對 CM7 TCM 進(jìn)行 Sparse write(隨機地址短小數(shù)據(jù)寫入操作)時可能會導(dǎo)致數(shù)據(jù)出錯,PXP 就是其一,解決方案就是 CM7 TCM 不要作為目的 FrameBuffer。
- Note:列出來的有限制的主設(shè)備大多是 RT1170 里新增的外設(shè)(CAAM, ENET_1G, ENET_QOS, GC355, LCDIFv2),除了 PXP 是 RT10xx 上也存在的,但是 RT10xx PXP 并沒有這個限制。
三、在PXP下實測數(shù)據(jù)搬移
要實測 PXP 數(shù)據(jù)搬移功能可以直接借助 SDK_2_16_000_MIMXRT1170-EVKBboardsevkbmimxrt1170driver_examplespxpcopy_piccm7 例程,其主要函數(shù) APP_CopyPicture() 摘錄如下,代碼清晰明了。我們要做不同的測試,只需要將 s_inputBuf、s_outputBuf 分別鏈接在不同存儲器空間里,并且設(shè)置不同的拷貝塊大小與坐標(biāo)位置即可。
- Note:僅需調(diào)整 COPY_WIDTH、DEST_OFFSET_X 值來測試對一維數(shù)據(jù)搬移影響(數(shù)據(jù)長度、起始地址對齊因素)
#include?"fsl_pxp.h"
//?源/目標(biāo)?Buffer?長寬設(shè)置(為測試方便,可設(shè)置成一樣)
#define?BUF_WIDTH???64
#define?BUF_HEIGHT??64
//?拷貝塊長寬及在目標(biāo)?Buffer?坐標(biāo)設(shè)置(從源?Buffer?坐標(biāo)固定為?[0,0])
#define?COPY_WIDTH????????8
#define?COPY_HEIGHT???????8
#define?DEST_OFFSET_X?????1
#define?DEST_OFFSET_Y?????1
uint16_t?s_inputBuf[BUF_HEIGHT][BUF_WIDTH];
uint16_t?s_outputBuf[BUF_HEIGHT][BUF_WIDTH];
static?void?APP_CopyPicture(void)
{
????pxp_pic_copy_config_t?pxpCopyConfig;
????//?設(shè)置拷貝參數(shù)(將s_inputBuf里坐標(biāo)[0,0]開始的大小為8x8的數(shù)據(jù)拷貝到s_outputBuf里[1,1]位置處)
????//?源?Buffer?地址與拷貝塊坐標(biāo)設(shè)置
????pxpCopyConfig.srcPicBaseAddr??=?(uint32_t)s_inputBuf;
????pxpCopyConfig.srcPitchBytes???=?sizeof(uint16_t)?*?BUF_WIDTH;
????pxpCopyConfig.srcOffsetX??????=?0;
????pxpCopyConfig.srcOffsetY??????=?0;
????//?目的?Buffer?地址與拷貝塊坐標(biāo)設(shè)置
????pxpCopyConfig.destPicBaseAddr?=?(uint32_t)s_outputBuf;
????pxpCopyConfig.destPitchBytes??=?sizeof(uint16_t)?*?BUF_WIDTH;
????pxpCopyConfig.destOffsetX?????=?DEST_OFFSET_X;
????pxpCopyConfig.destOffsetY?????=?DEST_OFFSET_Y;
????//?拷貝塊大小設(shè)置(像素點格式為?RGB565?即?2bytes)
????pxpCopyConfig.width???????????=?COPY_WIDTH;
????pxpCopyConfig.height??????????=?COPY_HEIGHT;
????pxpCopyConfig.pixelFormat?????=?kPXP_AsPixelFormatRGB565;
????//?啟動拷貝(將拷貝塊數(shù)據(jù)從源?Buffer?搬移到目的?Buffer)
????PXP_StartPictureCopy(PXP,?&pxpCopyConfig);
????while?(!(kPXP_CompleteFlag?&?PXP_GetStatusFlags(PXP)));
????PXP_ClearStatusFlags(PXP,?kPXP_CompleteFlag);
}
經(jīng)測試當(dāng) s_outputBuf 放在 OCRAM 或者外部 RAM 空間里時,搬移結(jié)果完全如預(yù)期。而當(dāng) s_outputBuf 放在 CM7 ITCM 或者 DTCM 時,則會出現(xiàn)異常結(jié)果,在 ITCM/DTCM 異常表現(xiàn)是一致的。
設(shè)置不同的 COPY_WIDTH、DEST_OFFSET_X 值組合帶來的異常結(jié)果不盡相同,這里僅放出一個 COPY_WIDTH = 1、DEST_OFFSET_X = 3 的情況供參考,可以看到除了目標(biāo)地址數(shù)據(jù)之外,前后還會有一些額外數(shù)據(jù)被寫入,這樣的數(shù)據(jù)搬移操作顯然不可靠了。
當(dāng)然并不是 s_outputBuf 放在 CM7 TCM 就一定能引起異常,只要拷貝的一維數(shù)據(jù)長度是 16bytes 整數(shù)倍,且目的起始地址以 8 對齊時,此時并無出錯情況發(fā)生。不滿足這個條件的寫入我們即稱之為有風(fēng)險的 Sparse write(隨機地址短小數(shù)據(jù)寫入)。
至此,在i.MXRT1170上PXP對CM7 TCM進(jìn)行隨機地址短小數(shù)據(jù)寫入操作限制痞子衡便介紹完畢了,掌聲在哪里~~~