
/******************************************************************************
*@file  : app.c
*@brief : application
*@ver   : 1.0.0
*@date  : 2022.10.20
******************************************************************************/

#include "app.h"   




void HAL_EXMC_MspInit(EXMC_HandleTypeDef *hexmc)
{
    GPIO_InitTypeDef GPIO_Init_PSRAM;
    /* Enable EXMC clock */
    __HAL_RCC_EXMC_CLK_ENABLE();

    /* Enable GPIOs clock */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();

    /*-- GPIO 配置 -----------------------------------------------------*/

    /* 通用 GPIO 配置 */
    GPIO_Init_PSRAM.Mode  = GPIO_MODE_AF_PP;       //配置为复用功能
    GPIO_Init_PSRAM.Alternate = GPIO_FUNCTION_10;  
    GPIO_Init_PSRAM.Drive = GPIO_DRIVE_LEVEL3;
    GPIO_Init_PSRAM.Pull = GPIO_PULLUP;   

    /*A地址信号线 针对引脚配置*/
    GPIO_Init_PSRAM.Pin = EXMC_A0_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A0_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A1_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A1_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A2_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A2_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A3_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A3_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A4_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A4_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A5_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A5_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A6_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A6_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A7_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A7_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A8_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A8_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A9_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A9_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A10_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A10_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A11_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A11_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A12_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A12_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A13_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A13_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A14_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A14_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A15_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A15_GPIO_PORT, &GPIO_Init_PSRAM);	

    GPIO_Init_PSRAM.Pin = EXMC_A16_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A16_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A17_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A17_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A18_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A18_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A19_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A19_GPIO_PORT, &GPIO_Init_PSRAM);  

    GPIO_Init_PSRAM.Pin = EXMC_A20_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A20_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_A21_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_A21_GPIO_PORT, &GPIO_Init_PSRAM);    

    /*DQ数据信号线 针对引脚配置*/
    GPIO_Init_PSRAM.Pin = EXMC_D0_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D0_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D1_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D1_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D2_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D2_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D3_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D3_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D4_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D4_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D5_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D5_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D6_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D6_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D7_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D7_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D8_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D8_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D9_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D9_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D10_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D10_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D11_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D11_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D12_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D12_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D13_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D13_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D14_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D14_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_D15_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_D15_GPIO_PORT, &GPIO_Init_PSRAM);

    /*控制信号线*/
    GPIO_Init_PSRAM.Pin = EXMC_PSRAM_CS_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_PSRAM_CS_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_WE_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_WE_GPIO_PORT, &GPIO_Init_PSRAM);

    GPIO_Init_PSRAM.Pin = EXMC_OE_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_OE_GPIO_PORT, &GPIO_Init_PSRAM);    

    GPIO_Init_PSRAM.Pin = EXMC_UDQM_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_UDQM_GPIO_PORT, &GPIO_Init_PSRAM);  

    GPIO_Init_PSRAM.Pin = EXMC_LDQM_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_LDQM_GPIO_PORT, &GPIO_Init_PSRAM);  

    GPIO_Init_PSRAM.Pin = EXMC_NWATI_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_NWATI_GPIO_PORT, &GPIO_Init_PSRAM); 

    GPIO_Init_PSRAM.Pin = EXMC_CLK_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_CLK_GPIO_PORT, &GPIO_Init_PSRAM); 

    GPIO_Init_PSRAM.Pin = EXMC_NADV_GPIO_PIN; 
    HAL_GPIO_Init(EXMC_NADV_GPIO_PORT, &GPIO_Init_PSRAM); 

    GPIO_Init_PSRAM.Pin = PSRAM_CRE_GPIO_PIN; 
    GPIO_Init_PSRAM.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init_PSRAM.Drive = GPIO_DRIVE_LEVEL3;
    HAL_GPIO_Init(PSRAM_CRE_GPIO_PORT, &GPIO_Init_PSRAM);  


}

/******************************************************************************
* @brief : EXMC asynchronous mode initialization function.
* @param : None
* @return: none
******************************************************************************/
void EXMC_PSRAM_Init_Asynchronous(void)
{
    EXMC_HandleTypeDef hpsram;
    hpsram.Instance                    = EXMC;
    hpsram.Instance_EX                 = EXMC_Ex;
    hpsram.Init.NSBank                 = EXMC_NORSRAM_BANK3;//use CS3 control，Addr=0x68000000
    hpsram.Init.DataAddressMux         = EXMC_DATA_ADDRESS_MUX_DISABLE;
    hpsram.Init.MemoryType             = EXMC_MEMORY_TYPE_PSRAM;
    hpsram.Init.MemoryDataWidth        = EXMC_NORSRAM_MEM_BUS_WIDTH_16;
    hpsram.Init.BurstAccessMode        = EXMC_BURST_ACCESS_MODE_DISABLE;
    hpsram.Init.NwaitSignalPolarity    = EXMC_WAIT_SIGNAL_POLARITY_HIGH;
    hpsram.Init.WrapMode               = EXMC_WRAP_MODE_DISABLE;
    hpsram.Init.SynchronousNwaitCfg    = EXMC_WAIT_TIMING_BEFORE_WS;
    hpsram.Init.WriteEN                = EXMC_WRITE_ENABLE;    
    hpsram.Init.NwaitEN                = EXMC_WAIT_SIGNAL_DISABLE;
    hpsram.Init.ExtendedMode           = EXMC_EXTENDED_MODE_ENABLE;
    hpsram.Init.AsynchronousWait       = EXMC_ASYNCHRONOUS_WAIT_DISABLE;
    hpsram.Init.WriteMode              = EXMC_WRITE_BURST_DISABLE;
    hpsram.Init.PageSize               = 0x00;
    /* PSRAM device configuration */  
    hpsram.Timing.AddressSetupTime       = 1;
    hpsram.Timing.DataSetupTime          = 3;
    hpsram.Timing.AddressHoldTime        = 1;   

    hpsram.Timing.BusTurnAroundDuration  = 0x06;

    hpsram.Timing.CLKDivision            = 0;
    hpsram.Timing.DataLatency            = 0;
    hpsram.Timing.AccessMode             = EXMC_ACCESS_MODE_D;

    hpsram.WTiming.AddressSetupTime       = 1;
    hpsram.WTiming.DataSetupTime          = 3;
    hpsram.WTiming.AddressHoldTime        = 1;   

    hpsram.WTiming.BusTurnAroundDuration  = 0x06;

    hpsram.WTiming.CLKDivision            = 0;
    hpsram.WTiming.DataLatency            = 0;
    hpsram.WTiming.AccessMode             = EXMC_ACCESS_MODE_D;


    HAL_EXMC_Init(&hpsram);
}

/******************************************************************************
* @brief : EXMC synchronous Mode Initialization Function.
* @param : None
* @return: none
******************************************************************************/
void EXMC_PSRAM_Init_Synchronous(void)
{
    EXMC_HandleTypeDef hpsram;
    hpsram.Instance                    = EXMC;
    hpsram.Init.NSBank                 = EXMC_NORSRAM_BANK3;//use CS3 control，Addr=0x68000000
    hpsram.Init.DataAddressMux         = EXMC_DATA_ADDRESS_MUX_DISABLE;
    hpsram.Init.MemoryType             = EXMC_MEMORY_TYPE_PSRAM;
    hpsram.Init.MemoryDataWidth        = EXMC_NORSRAM_MEM_BUS_WIDTH_16;
    hpsram.Init.BurstAccessMode        = EXMC_BURST_ACCESS_MODE_ENABLE;
    hpsram.Init.NwaitSignalPolarity    = EXMC_WAIT_SIGNAL_POLARITY_HIGH;
    hpsram.Init.WrapMode               = EXMC_WRAP_MODE_ENABLE;
    hpsram.Init.SynchronousNwaitCfg    = EXMC_WAIT_TIMING_DURING_WS;
    hpsram.Init.WriteEN                = EXMC_WRITE_ENABLE;   
    hpsram.Init.NwaitEN                = EXMC_WAIT_SIGNAL_ENABLE;
    hpsram.Init.ExtendedMode           = EXMC_EXTENDED_MODE_DISABLE;
    hpsram.Init.AsynchronousWait       = EXMC_ASYNCHRONOUS_WAIT_ENABLE;
    hpsram.Init.WriteMode              = EXMC_WRITE_BURST_ENABLE;
    hpsram.Init.PageSize               = 0x00; 

    /* PSRAM device configuration */  
    hpsram.Timing.AddressSetupTime       = 1;
    hpsram.Timing.DataSetupTime          = 3;
    hpsram.Timing.AddressHoldTime        = 1;   

    hpsram.Timing.BusTurnAroundDuration  = 0x06;

    hpsram.Timing.CLKDivision            = 4;
    hpsram.Timing.DataLatency            = 0;
    hpsram.Timing.AccessMode             = EXMC_ACCESS_MODE_A;//PSRAM

    HAL_EXMC_Init(&hpsram);
}


static void PSRAM_Read_Write_Test(void)
{
    /*写入数据计数器*/
    uint32_t counter=0;

    /* 8位的数据 */
    uint8_t u8WriteData = 0x5A, u8ReadData = 0;  

    /* 16位的数据 */
    uint16_t u16WriteData = 0x3CC3, u16ReadData = 0; 

    /* 32位的数据 */
    uint32_t u32WriteData = 0x55AA33CC, u32ReadData = 0; 

    HAL_SimpleDelay(5000);
    
   
    printfS("Detecting PSRAM, reading and writing sdram in 8-bit mode...\r\n");
    
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE; counter++)
    {
        *(__IO uint8_t*) (EXMC_BANK_PSRAM + counter) = (uint8_t)(0x00);
    }
    
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE; counter++)
    {
        *(__IO uint8_t*) (EXMC_BANK_PSRAM + counter) = (uint8_t)(u8WriteData + counter);
    }
    
    for(counter = 0; counter< IS66WVC4M16EALL_SIZE;counter++ )
    {
        u8ReadData = *(__IO uint8_t*)(EXMC_BANK_PSRAM + counter);  //从该地址读出数据

        if(u8ReadData != (uint8_t)(u8WriteData + counter))      //检测数据，若不相等，跳出函数,返回检测失败结果。
        {
            printfS("8-bit data read and write errors,u8ReadData = 0x%02x,u8WriteData=0x%02x,counter=%d\r\n",u8ReadData,u8WriteData,counter);
            return;
        }
    }

    HAL_SimpleDelay(5000);
  
    printfS("Detecting PSRAM, reading and writing sdram in 16-bit mode...\r\n");
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE;counter+=2)
    {
        *(__IO uint16_t*) (EXMC_BANK_PSRAM + counter) = (uint16_t)(0x0000);
    }    
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE;counter+=2)
    {
        *(__IO uint16_t*) (EXMC_BANK_PSRAM + counter) = (uint16_t)(u16WriteData + counter/2);
    }
    for(counter = 0; counter< IS66WVC4M16EALL_SIZE;counter+=2)
    {
        u16ReadData = *(__IO uint16_t*)(EXMC_BANK_PSRAM + counter);  //从该地址读出数据

        if(u16ReadData != (uint16_t)(u16WriteData + counter/2))       //检测数据，若不相等，跳出函数,返回检测失败结果。
        {
            printfS("16-bit data read and write errors,u16ReadData = 0x%04x,u16WriteData=0x%04x,counter=%d\r\n",u16ReadData,u16WriteData,counter);
            return;
        }
    }
   
    HAL_SimpleDelay(5000);
       
    printfS("Detecting PSRAM, reading and writing sdram in 32-bit mode...\r\n");
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE;counter+=4)
    {
        *(__IO uint32_t*) (EXMC_BANK_PSRAM + counter) = (uint32_t)(0x00000000);
    }
    for (counter = 0; counter < IS66WVC4M16EALL_SIZE;counter+=4)
    {
        *(__IO uint32_t*) (EXMC_BANK_PSRAM + counter) = (uint32_t)(u32WriteData + counter/4);
    }
    for(counter = 0; counter< IS66WVC4M16EALL_SIZE/4;counter+=4)
    {
        u32ReadData = *(__IO uint32_t*)(EXMC_BANK_PSRAM + counter);  //从该地址读出数据

        if(u32ReadData != (uint32_t)(u32WriteData + counter/4))      //检测数据，若不相等，跳出函数,返回检测失败结果。
        {
            printfS("32-bit data read and write errors,u32ReadData=0x%08x,u32WriteData=0x%08x,counter=%d\r\n",u32ReadData,u32WriteData,counter);
            return;
        }
    }
    
    HAL_SimpleDelay(5000);

    printfS("PSRAM read and write test successful!\r\n"); 
}


void APP_PSRAM_Test(void)
{  
    printfS("Start PSRAM test!\r\n");  
    uint32_t temp=0;
    
    EXMC_PSRAM_Init_Asynchronous();
    
    HAL_SimpleDelay(5000);
    
    *( uint16_t*) (EXMC_BANK_PSRAM+0) =   (uint16_t)0x5AA5; 
    *( uint16_t*) (EXMC_BANK_PSRAM+2) =   (uint16_t)0x3CC3; 
    *( uint16_t*) (EXMC_BANK_PSRAM+4) =   (uint16_t)0x55AA; 
    *( uint16_t*) (EXMC_BANK_PSRAM+6) =   (uint16_t)0xAA55; 
    *( uint16_t*) (EXMC_BANK_PSRAM+8) =   (uint16_t)0x33CC; 
    *( uint16_t*) (EXMC_BANK_PSRAM+10) =  (uint16_t)0xCC33; 
    
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+0); 
    printfS("data=0x%X \r\n",temp);   
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+2);   
    printfS("data=0x%X \r\n",temp);   
    temp =  *( uint16_t*)(EXMC_BANK_PSRAM+4);   
    printfS("data=0x%X \r\n",temp);   
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+6);
    printfS("data=0x%X \r\n",temp);   
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+8);   
    printfS("data=0x%X \r\n",temp); 
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+10);   
    printfS("data=0x%X \r\n",temp); 
    
    HAL_GPIO_WritePin(PSRAM_CRE_GPIO_PORT, PSRAM_CRE_GPIO_PIN, GPIO_PIN_SET);
    *( uint16_t*) (EXMC_BANK_PSRAM+0x10383E) =1 ; //选择同步模式
    temp =  *( uint16_t*) (EXMC_BANK_PSRAM+0x10383E); 
    printfS("BCR=0x%X \r\n",temp);
    HAL_GPIO_WritePin(PSRAM_CRE_GPIO_PORT, PSRAM_CRE_GPIO_PIN, GPIO_PIN_RESET);  

    EXMC_PSRAM_Init_Synchronous();

    PSRAM_Read_Write_Test();
}




