99久久全国免费观看_国产一区二区三区四区五区VM_久久www人成免费看片中文_国产高清在线a视频大全_深夜福利www_日韩一级成人av

無緩存下對Flash的AHB讀訪問竟然是這樣

大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是實抓Flash信號波形來看i.MXRT的FlexSPI外設下AHB讀訪問情形

上一篇文章 《i.MXRT中FlexSPI外設對AHB Burst Read特性的支持》 里痞子衡介紹了FlexSPI外設在不開啟Prefetch功能下響應AHB master的訪問請求完全受AHB總線Burst Read特性決定,這是FlexSPI外設最基礎的對Flash訪問支持功能,研究這個其實是很有意義的,這可以反映出XiP下最原始的代碼執行效率。

我們知道在實際項目中,XiP應用程序常常是在L1 Cache和Prefetch加持下運行的,代碼執行效率會得到大大提升,但無論是怎樣的緩存策略,極限情況下(比如大數據塊搬移,長跳轉指令)最終還是拼得FlexSPI最基礎的讀訪問支持。今天痞子衡就從抓Flash信號波形角度帶大家真切感受下這最基礎的AHB讀訪問情形(為更清晰地分析結果,本次主要涉及數據總線AHB訪問,暫不涉及指令總線AHB訪問):

一、實驗準備

痞子衡用i.MXRT1050-EVKB來做這個AHB讀訪問實驗,這塊板子上的Flash被痞子衡更換過,目前的型號是華邦W25Q64JWS-IQ。我們基于 \SDK_2.9.1_EVKB-IMXRT1050\boards\evkbimxrt1050\demo_apps\led_blinky\iar 例程(記得切換到 flexspi_nor_debug build)來簡單修改一下,把啟動頭FDCB修改如下,設置Flash工作于30MHz Fast Read Quad I/O SDR模式,調成30MHz低速是為了方便后續用示波器抓Flash信號去分析。

const flexspi_nor_config_t qspiflash_config = {
    .memConfig =
        {
            .tag              = FLEXSPI_CFG_BLK_TAG,
            .version          = FLEXSPI_CFG_BLK_VERSION,
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
            .csHoldTime       = 3u,
            .csSetupTime      = 3u,
            .controllerMiscOption = 0x10,
            .deviceType       = kFlexSpiDeviceType_SerialNOR,
            .sflashPadType    = kSerialFlash_4Pads,
            // Flash工作于30MHz
            .serialClkFreq    = kFlexSpiSerialClk_30MHz,
            .sflashA1Size     = 8u * 1024u * 1024u,
            .lookupTable =
                {
                    // Quad I/O Fast Read SDR LUTs
                    [4*CMD_LUT_SEQ_IDX_READ + 0] = FLEXSPI_LUT_SEQ(CMD_SDR,   FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
                    [4*CMD_LUT_SEQ_IDX_READ + 1] = FLEXSPI_LUT_SEQ(MODE8_SDR, FLEXSPI_4PAD, 0xF0, DUMMY_SDR, FLEXSPI_4PAD, 0x04),
                    [4*CMD_LUT_SEQ_IDX_READ + 2] = FLEXSPI_LUT_SEQ(READ_SDR,  FLEXSPI_4PAD, 0x04, STOP,      FLEXSPI_1PAD, 0x00),
                    [4*CMD_LUT_SEQ_IDX_READ + 3] = 0,
                },
        },
    .pageSize           = 256u,
    .sectorSize         = 4u * 1024u,
    .blockSize          = 64u * 1024u,
    .isUniformBlockSize = false,
};

下圖是華邦W25Q64JWS-IQ芯片的Fast Read Quad I/O SDR傳輸時序圖,Dummy Cycle連同MODE8_SDR序列一共6個SCK周期,此外還有個特別注意點,MODE8_SDR序列參數值需要被設成0xFx,我們上面修改的FDCB啟動頭是符合要求的。

現在讓我們把示波器拿出來,四路探頭分別連到板載Flash器件的CE#、SCK、SI_IO0、SO_IO1引腳(IO2、IO3因探頭有限就不抓取了,IO[1:0]足夠我們分析時序了),然后將 led_blinky 工程下載進Flash運行便可以觀測結果了。

二、實驗代碼

因為我們下載的是一個XIP工程,代碼的執行本身也會觸發Flash中的指令讀取,這會影響我們在示波器上觀測AHB讀數據測試結果,所以我們可以在main()函數里把SysTick初始化去掉(不要中斷),并且調用如下ramfunc型函數 test_ahb_read() 來做測試(痞子衡直接利用了IAR軟件的特性),這樣代碼跑起來后,Flash上發生的讀訪問均來自我們想要測試的AHB讀數據操作(這也意味著ICache是否開啟對本系列測試結果沒有影響,但不管怎么,我們統一關掉):

Note: DCache和Prefetch必須要全部關閉,否則哪怕測試代碼里對同一個地方循環讀取,但在Flash引腳上根本看不到周期性信號波形,因為系統做了緩存,后續的讀取操作可能直接發生在緩存區里(32KB DCache, 1KB AHB RX prefetch buffer)了。

#define AHB_ADDR_START (0x60002400) 

#if (defined(__ICCARM__))
#pragma optimize = none
__ramfunc 
#endif
void test_ahb_read(void)
{
    /* Disable L1 I-Cache*/
    SCB_DisableICache();

    /* Disable L1 D-Cache*/
    SCB_DisableDCache();

    /* Disable FlexSPI AHB read prefetch */
    FLEXSPI->AHBCR &= ~(FLEXSPI_AHBCR_PREFETCHEN_MASK | FLEXSPI_AHBCR_CACHABLEEN_MASK);
    
    while (1)
    {
        SDK_DelayAtLeastUs(10, SystemCoreClock);
        for (uint32_t i = 1; i <= 8; i++)
        {   
            SDK_DelayAtLeastUs(2, SystemCoreClock);
            memcpy((void *)0x20200000, (void *)AHB_ADDR_START, i);
        }
    } 
}

因為我們用了memcpy來做Flash數據拷貝,memcpy功能實際上是IAR軟件自帶庫 ABImemcpy.a 里面的 __aeabi_memcpy、__aeabi_memcpy4、__aeabi_memcpy8 等函數實現的,因此我們還需要在工程鏈接文件里將 ABImemcpy.o 鏈接到RAM區;并且我們還用了SDK_DelayAtLeastUs()來分隔每次memcpy()波形結果,還需要將這個函數里調用的相關代碼放到RAM區(fsl_common.c里)。

initialize by copy { readwrite,
                     section .textrw,
                     // 確保 memcpy() 相關代碼全在RAM里
                     object ABImemcpy.o,
                     // 確保 SDK_DelayAtLeastUs() 相關代碼全在RAM里
                     object fsl_common.o,
                     object I64DivZer.o,
                     object I64DivMod.o
                     };
do not initialize  { section .noinit };

一切準備就緒后具體測試就是設置不同的AHB_ADDR_START值(這里主要是考慮地址對齊)來觀測Flash信號的實際波形。此外為了便于分辨IO[1:0]上的數據,我們最好定義一塊特殊const數據區,根據Flash傳輸時序圖,其中數據Byte[4]和Byte[0]是在IO0線上傳輸、Byte[5]和Byte[1]是在IO1線上傳輸的,這4bit共有16種不同值組合,我們將這16種不同值放在ahbRdBlock[16]數組中,并將其鏈接在 0x60002400 - 0x6000240f 地址空間里。

// 在工程源文件中
const uint8_t ahbRdBlock[16] @ ".ahbRdBuffer" = {0x00, 0x01, 0x02, 0x03,
                                                 0x10, 0x11, 0x12, 0x13,
                                                 0x20, 0x21, 0x22, 0x23,
                                                 0x30, 0x31, 0x32, 0x33};
// 在工程鏈接文件中
keep{ section .ahbRdBuffer };
place at address mem:0x60002400 { readonly section .ahbRdBuffer };

三、實驗結果

3.1 AHB_ADDR_START = 0x6002400 即八字節對齊

我們先來看AHB_ADDR_START = 0x6002400時抓取一次完整for循環結果的波形(見下圖),可以看到在八字節對齊的地址下使用memcpy拷貝1/2/4/8字節,均僅產生一次CS信號有效周期(拉低),在這CS有效期間完成全部所需數據的讀取。但是拷貝3/5/6/7字節時,會拆分出多個CS有效周期。

當使用memcpy拷貝3/5/6字節時,會拆分出2個CS有效周期(見下圖),這里第一個CS周期看起來似乎是多余的,為什么是這種結果,這需要深入研究AHB機制(痞子衡會另寫文章分析);

當拷貝3字節時,第一個CS周期實際讀取了前2個字節 [0x60002400, 0x60002401],第二個CS周期讀取了全部3字節 [0x60002400, 0x60002402]。

當拷貝5字節時,第一個CS周期實際讀取了前4個字節 [0x60002400, 0x60002403],第二個CS周期讀取了全部5字節 [0x60002400, 0x60002404]。

當拷貝6字節時,第一個CS周期實際讀取了前4個字節 [0x60002400, 0x60002403],第二個CS周期讀取了全部6字節 [0x60002400, 0x60002405]。

當使用memcpy拷貝7字節時,會拆分出3個CS有效周期(見下圖),這里前兩個CS周期看起來似乎都是多余的;

當拷貝7字節時,第一個CS周期實際讀取了前4個字節 [0x60002400, 0x60002403],第二個CS周期實際讀取了前6個字節 [0x60002400, 0x60002405],第三個CS周期讀取了全部7字節 [0x60002400, 0x60002406]。

3.2 AHB_ADDR_START = 0x6002404 即四字節對齊

AHB_ADDR_START = 0x6002404時抓取一次完整for循環結果的波形(見下圖),可以看到在四字節對齊的地址下使用memcpy拷貝1/2/4字節,均僅產生一次CS信號有效周期(拉低),在這CS有效期間完成全部所需數據的讀取。

但是拷貝3/5/6/7/8字節時,會拆分出多個CS有效周期。不過其中拷貝5/6/8字節,是合理的拆分,并沒有冗余讀取。

3.3 AHB_ADDR_START = 0x6002401 即奇地址

AHB_ADDR_START = 0x6002401時抓取一次完整for循環結果的波形(見下圖),這種情況下CS拆分特別嚴重,幾乎都存在冗余讀取。

3.4 AHB_ADDR_START = 0x6002402 即偶地址

AHB_ADDR_START = 0x6002402時抓取一次完整for循環結果的波形(見下圖),這種情況下CS拆分特別嚴重,幾乎都存在冗余讀取。

3.5 AHB_ADDR_START = 0x6002403

AHB_ADDR_START = 0x6002403時抓取一次完整for循環結果的波形(見下圖),這種情況下CS拆分特別嚴重,幾乎都存在冗余讀取。

至此,實抓Flash信號波形來看i.MXRT的FlexSPI外設下AHB讀訪問情形痞子衡便介紹完畢了,掌聲在哪里~~~

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 1
收藏 2
關注 41
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧
主站蜘蛛池模板: 少妇下面好紧好爽视频 | 97免费视频在线观看 | 精品国产人妻一区二区三区 | 国产精品无码av无码 | 日本黄色免费片 | 黄色在线视频观看 | 少妇被粗大的猛烈进出动态图片 | 性xxxx乱又伦| 正在播放长泽梓免费观看 | 日本亚洲欧洲色α | 中文字幕国产视频 | 国产欧美日韩高清 | 成人免费在线观看网站 | 日本熟妇另类视频在线播放 | 国产伦精品免费视频 | 成人免费高清在线播放 | 可以免费看av | 日韩熟女精品一区二区三区 | A级日本乱理伦片免费入口 四虎精品免费 | 少妇丰满大乳被男人揉捏视频 | 99热99在线观看 | 女人和男人视频网站 | 亚洲久悠悠色悠在线播放 | 国产线观看免费观看 | 69精产国品一二三产品价格 | 老少配videoshd乱配 | 午夜精品成人一区二区 | 国产视频xxx | 在线观看中文视频 | 免费av免费看 | 性欧美人与zozoxxxx视频 | 亚洲欧美日韩中文加勒比 | 成人免费网址 | 网红主播大秀福利视频日韩精品 | 97国产情侣爱久久免费观看 | 中文字幕AV无码免费一区 | 日韩网站一区二区 | 免费一级片网站 | 欧美黑人XXXX高潮猛交 | 国产伦精品免费视频 | 少妇乳大丰满在线播放 |