FlexBus外擴PSRAM 應用實例詳解


前段時間項目遇到瓶頸,片內RAM空間不足,想要解決這個問題要麼換更大RAMMCU,要麼就外擴PSRAM。惋惜所用的K21最大就128Kb,沒有更大的了,因此只有選擇外擴。方案選擇主要有兩個問題須要考慮:1.PSRAM的數據位數;2.是否使用鎖存器。因爲IO口資源有限,同時爲保證片外PSRAM的速度。最終的方案選擇:16位數據的PSRAM,地址數據複用,兩個鎖存器切換數據地址方案。因爲在網上沒有找到先例,因此硬件接法有不少不肯定。如今分享給罈子裏的小夥伴們,歡迎指教。app

相信看這篇文章的或多或少也知道FlexbusPSRAM是什麼了吧,因此在這兒就不囉嗦講FlexbusPSRAM的基本概念。實在有不懂的小夥伴百度一下,你就知道!ide

硬件部分函數

下面仔細來看看硬件框圖吧,下面框圖主要是FlexbusPSRAM的接法。測試



wKiom1RZ1xrS0F6gAAG94s5TRto624.jpg




根據上面框圖作以下說明:flex

1. PSRAM16位數據線接FB_AD[15:0],地址線接FB_AD[20:1]。其中地址線的FB_AD[16:1]與數據複用。採用雙鎖存器鎖存地址。可能有的小夥伴就會產生疑惑了,爲何FlexbusFB_AD[16:1]PSRAMA[15:0]呢?稍後解答!ui

2. 總線的FB_ALE接鎖存器的鎖存信號LE,用過鎖存器的小夥伴都知道鎖存器還有一個片選信號(讓鎖存器工做的開關),這個信號就隨便接MCUIO口便可。spa

3. FlexbusFB_CE,FB_OE,FB_WE分別要與PSRAMCE,OE,WE鏈接。操作系統

4. FlexbusFB_BE31_24,FB_BE23_16分別與UB,LB鏈接,爲何呢?blog

5. PSRAM還有一個ZZ引腳,控制PSRAM是否休眠的,若是須要接MCUIO口便可接口

由於不一樣的MCUFlexbus所映射的IO不同,因此就整理了一下用框圖來講明。有什麼疑問歡迎留言討論。下面解答剛剛提出的兩個爲何。

1. 爲何FlexbusFB_AD[16:1]PSRAMA[15:0]

關於這個問題,只要理解MCU處理器的尋址和PSRAM芯片的尋址就明白了。

目前最流行的32位嵌入式處理器ARM處理器,固然我所用的Cortex-M4處理器也是RAM家族的。從處理器的角度看,系統中每一個地址對應的是一個BYTE的數據單元。這和不少別的處理器是同樣的。

16位的PSRAM芯片或者工做在16-BIT模式的芯片來講,一個地址對應16-BIT的數據。說到這裏想必小夥伴們都懂了吧。也就不囉嗦了。

 

2. 爲何FlexbusFB_BE31_24,FB_BE23_16分別與UB,LB鏈接?

其實這個沒有什麼好說的,看MCU flexbusdatasheet就能找到。在此順便提一下。

 

wKiom1RZ15TzKH62AACTCqeahmY162.jpg

wKioL1RZ1_fwYlxAAAD7Y78B2bc463.jpg


 

 

咱們這裏是右對齊模式,從上圖可知,軟件CSCRn[BLS]應設爲PSRAMUB須要接FB_BE31_24LU須要接FB_BE23_16

軟件部分

硬件就已經講述完畢,接下來是軟件部分。我這裏使用的MQX4.0操做系統,MCUK21。配置函數以下,不一樣的平臺和MCU程序的表現形式不同,配置的寄存器都是同樣的,這裏須要小夥伴們觸類旁通喔。

#define GPIO_PIN_MASK            0x1Fu
#define GPIO_PINX(x)              (((1)<<(x & GPIO_PIN_MASK)))
/*FUNCTION*---------------------------------------------------------------------
* Function Name    : flexbus_setup
* Returned Value   :  none
* Comments         :
*    Setup FlexBus pins before PSRAM operation
*END*-------------------------------------------------------------------------*/
 void flexbus_setup (void)
{
    #define ALT5                    0x05
    #define OFF_CHIP_ACCESS_ALLOW   3
    PORT_MemMapPtr  pctl;
    SIM_MemMapPtr   sim = SIM_BASE_PTR;
    /* Enable clock to FlexBus module */
    sim->SCGC7 |= SIM_SCGC7_FLEXBUS_MASK;
    sim->CLKDIV1 |= SIM_CLKDIV1_OUTDIV3(0x0);//flexbus not divided
    #ifdef SIM_SOPT2_FBSL
        sim->SOPT2 |= SIM_SOPT2_FBSL(OFF_CHIP_ACCESS_ALLOW);
    #endif
//把對應的接口配置成總線模式
            pctl = (PORT_MemMapPtr)PORTB_BASE_PTR;
pctl->PCR[9] = PORT_PCR_MUX(ALT5); /* FB_AD20 */
            pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_AD19 */
            pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_AD18 */
            pctl->PCR[16] = PORT_PCR_MUX(ALT5); /* FB_AD17 */
            pctl->PCR[17] = PORT_PCR_MUX(ALT5); /* FB_AD16 */
            pctl->PCR[18] = PORT_PCR_MUX(ALT5); /* FB_AD15 */
            pctl->PCR[19] = PORT_PCR_MUX(ALT5); /* FB_OE_B */
           // pctl->PCR[20] = PORT_PCR_MUX(ALT5); /* FB_AD31 */
           //pctl->PCR[21] = PORT_PCR_MUX(ALT5); /* FB_AD30 */
           // pctl->PCR[22] = PORT_PCR_MUX(ALT5); /* FB_AD29 */
           // pctl->PCR[23] = PORT_PCR_MUX(ALT5); /* FB_AD28 */
            pctl = (PORT_MemMapPtr)PORTC_BASE_PTR;
            pctl->PCR[0] = PORT_PCR_MUX(ALT5); /* FB_AD14 */
            pctl->PCR[1] = PORT_PCR_MUX(ALT5); /* FB_AD13 */
            pctl->PCR[2] = PORT_PCR_MUX(ALT5); /* FB_AD12 */
            pctl->PCR[4] = PORT_PCR_MUX(ALT5); /* FB_AD11 */
            pctl->PCR[5] = PORT_PCR_MUX(ALT5); /* FB_AD10 */
            pctl->PCR[6] = PORT_PCR_MUX(ALT5); /* FB_AD9 */
            pctl->PCR[7] = PORT_PCR_MUX(ALT5); /* FB_AD8 */
            pctl->PCR[8] = PORT_PCR_MUX(ALT5); /* FB_AD7 */
            pctl->PCR[9] = PORT_PCR_MUX(ALT5); /* FB_AD6 */
            pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_AD5 */
            pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_RW_B */
            pctl->PCR[16] = PORT_PCR_MUX(ALT5); /* FB_BE23_16 */
            pctl->PCR[17] = PORT_PCR_MUX(ALT5); /* FB_BE31_24 */
            pctl->PCR[3] = PORT_PCR_MUX(ALT5); /* FB_CLKOUT */
            pctl = (PORT_MemMapPtr)PORTD_BASE_PTR;
            pctl->PCR[0] = PORT_PCR_MUX(ALT5); /* FB_ALE */
            pctl->PCR[1] = PORT_PCR_MUX(ALT5); /* FB_CS0_b */
            pctl->PCR[2] = PORT_PCR_MUX(ALT5); /* FB_AD4 */
            pctl->PCR[3] = PORT_PCR_MUX(ALT5); /* FB_AD3 */
            pctl->PCR[4] = PORT_PCR_MUX(ALT5); /* FB_AD2 */
            pctl->PCR[5] = PORT_PCR_MUX(ALT5); /* FB_AD1 */
            pctl->PCR[6] = PORT_PCR_MUX(ALT5); /* FB_AD0 */
    //若是FB_AD口被其餘功能佔用,接口僅作地址線,可用flexbus的專用地址線FB_Ax代替,只需硬件上鍊接軟件把對應IO配成總線模式便可
            //pctl->PCR[10] = PORT_PCR_MUX(ALT5); /* FB_A18 */
            //pctl->PCR[11] = PORT_PCR_MUX(ALT5); /* FB_A19 */
            //pctl->PCR[12] = PORT_PCR_MUX(ALT5); /* FB_A20 */
              //Set PIN for GPIO functionality
              PORTC_PCR12 = (0|PORT_PCR_MUX(1));//PSRAM_ZZ腳
              PORTB_PCR6  = (0|PORT_PCR_MUX(1));//573 OE腳
            // GPIOB_PDDR=GPIO_PDDR_PDD(GPIO_PINX(16));
              //Change PINto outputs
              GPIOC_PDDR=GPIO_PDDR_PDD(GPIO_PINX(12));
              GPIOB_PDDR=GPIO_PDDR_PDD(GPIO_PINX(6));
              GPIOC_PDOR=GPIO_PDOR_PDO(GPIO_PINX(12));
}
/*FUNCTION*---------------------------------------------------------------------
*
* Function Name    : _bsp_flexbus_psram_setup
* Returned Value   :
* Comments         :
*    Setup FlexBus for PSRAM operation
*
*END*-------------------------------------------------------------------------*/
 void flexbus_psram_setup ()
{
        FB_MemMapPtr fb_ptr = FB_BASE_PTR;
        /* Enable external MRAM mapped on CS0 */
        /* CS0 base address */
        fb_ptr->CS[0].CSAR = 0x60000000;
        /* CS0 control (16bit data, 2 wait state) */
        fb_ptr->CS[0].CSCR = FB_CSCR_BLS_MASK |//低16位
                             FB_CSCR_AA_MASK  |
                             FB_CSCR_WS(0X2)    |
                             FB_CSCR_ASET(0X1)    |
                             FB_CSCR_PS(2)    |
                             FB_CSCR_WRAH(1)   |
                             FB_CSCR_RDAH(1)   |
                             FB_CSCR_BEM_MASK;
    /* CS0 address mask and enable */
    fb_ptr->CS[0].CSMR = FB_CSMR_BAM(0x1F) | FB_CSMR_V_MASK;//2M
    fb_ptr->CSPMCR = FB_CSPMCR_GROUP3(2) | FB_CSPMCR_GROUP2(2);
}

關於Flexbus每一個寄存器的含義,詳參MCUdatasheet

 

可靠性測試方案

外擴PSRAM通常用作內存使用,咱們的應用程序的數據就是映射到片外的。因此PSRAM的可靠性必需要保證,必須是零容忍。否則就會出現異常死機的狀況。這對於產品來講是絕對不容許的。因此雖然硬件軟件已經通了,但對PSRAM的壓力測試仍是頗有必要的。

方案:對PSRAM循環遍歷讀寫不一樣數據並判斷所寫數據是否正確。源碼以下:

void test_psram(void)
{
    uint16 wdata16 = 0x5050;
    uint16 rdata16=0;
    uint32 n,i;
    int add;
    time++;
    wdata16 += time*16;
     for(n=0x0000;n<0x1ffff0;n+=2)
    {
      wdata16 += 1;
       add = n;
      *(vuint16*)(0x60000000+n) = wdata16;
        rdata16 = 0;
        rdata16 = (*(vuint16*)(0x60000000+n));
       if((wdata16) != (rdata16))
        {
            error++;                   printf("%d,%d,W=0x%4x,R=0x%4x,add=0x%4x\n",time,error,wdata16,rdata16,add);
       }
    }
    if(time%2 == 0)
     {
       printf("time = %d\n",time);
      }
}

關於PSRAM的穩定性有幾點須要分享給你們。

1.關於PSRAMIS66WVE1M16BLL)供電電壓,當初是採用3.3V供電,供應商也說3.3V供電沒問題。可是不能經過咱們的壓力測試,遍歷一次會有一些錯誤出現。芯片手冊上是3.0V供電。

2. 壓力測試,剛上電第一次遍歷會有幾個錯誤,其實比例很小,萬分之一的樣子。正如前面所說,對PSRAM的要求是零錯誤。因此這樣的問題仍然會影響咱們作出來的產品的質量,這個緣由很難找,後面咱們硬件上在鎖存器和PSRAM的片選處加了上拉電阻問題得以解決。多是上電時片選狀態未知,致使PSRAM處於一個未知狀態,修改了PSRAM什麼配置吧,具體什麼緣由我實在說不上來,在此分享給你們。若是有不一樣意見的,歡迎指教!

原創文章,歡迎評論,轉載標明出處,謝謝配合!

相關文章
相關標籤/搜索