/** ****************************************************************************** * @file bsp_sdram.c * @author fire * @version V1.0 * @date 2015-xx-xx * @brief sdram应用函数接口 ****************************************************************************** * @attention * * 实验平台:野火 STM32 H750 开发板 * 论坛 :http://www.chuxue123.com * 淘宝 :http://firestm32.taobao.com * ****************************************************************************** */ #include "./sdram/bsp_sdram.h" static FMC_SDRAM_CommandTypeDef Command; SDRAM_HandleTypeDef hsdram1; #define sdramHandle hsdram1 /** * @brief 延迟一段时间 * @param 延迟的时间长度 * @retval None */ static void SDRAM_delay(__IO uint32_t nCount) { __IO uint32_t index = 0; for(index = (100000 * nCount); index != 0; index--) { } } /** * @brief 初始化控制SDRAM的IO * @param 无 * @retval 无 */ static void SDRAM_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能SDRAM相关的IO时钟 */ /*地址信号线*/ FMC_A0_GPIO_CLK();FMC_A1_GPIO_CLK(); FMC_A2_GPIO_CLK(); FMC_A3_GPIO_CLK();FMC_A4_GPIO_CLK(); FMC_A5_GPIO_CLK(); FMC_A6_GPIO_CLK();FMC_A7_GPIO_CLK(); FMC_A8_GPIO_CLK(); FMC_A9_GPIO_CLK();FMC_A10_GPIO_CLK();FMC_A11_GPIO_CLK(); FMC_A12_GPIO_CLK(); /*数据信号线*/ FMC_D0_GPIO_CLK(); FMC_D1_GPIO_CLK() ; FMC_D2_GPIO_CLK() ; FMC_D3_GPIO_CLK(); FMC_D4_GPIO_CLK() ; FMC_D5_GPIO_CLK() ; FMC_D6_GPIO_CLK(); FMC_D7_GPIO_CLK() ; FMC_D8_GPIO_CLK() ; FMC_D9_GPIO_CLK(); FMC_D10_GPIO_CLK(); FMC_D11_GPIO_CLK(); FMC_D12_GPIO_CLK();FMC_D13_GPIO_CLK(); FMC_D14_GPIO_CLK(); FMC_D15_GPIO_CLK();FMC_D16_GPIO_CLK(); FMC_D17_GPIO_CLK(); FMC_D18_GPIO_CLK();FMC_D19_GPIO_CLK(); FMC_D20_GPIO_CLK(); FMC_D21_GPIO_CLK();FMC_D22_GPIO_CLK(); FMC_D23_GPIO_CLK(); FMC_D24_GPIO_CLK();FMC_D25_GPIO_CLK(); FMC_D26_GPIO_CLK(); FMC_D27_GPIO_CLK();FMC_D28_GPIO_CLK(); FMC_D29_GPIO_CLK(); FMC_D30_GPIO_CLK();FMC_D31_GPIO_CLK(); /*控制信号线*/ FMC_CS_GPIO_CLK() ; FMC_BA0_GPIO_CLK(); FMC_BA1_GPIO_CLK() ; FMC_WE_GPIO_CLK() ; FMC_RAS_GPIO_CLK(); FMC_CAS_GPIO_CLK(); FMC_CLK_GPIO_CLK(); FMC_CKE_GPIO_CLK(); FMC_UDQM_GPIO_CLK(); FMC_LDQM_GPIO_CLK();FMC_UDQM2_GPIO_CLK();FMC_LDQM2_GPIO_CLK(); /*-- SDRAM IO 配置 -----------------------------------------------------*/ GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;//配置为复用功能 GPIO_InitStructure.Pull = GPIO_PULLUP; GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStructure.Alternate = GPIO_AF12_FMC; /*地址信号线 针对引脚配置*/ GPIO_InitStructure.Pin = FMC_A0_GPIO_PIN; HAL_GPIO_Init(FMC_A0_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A1_GPIO_PIN; HAL_GPIO_Init(FMC_A1_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A2_GPIO_PIN; HAL_GPIO_Init(FMC_A2_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A3_GPIO_PIN; HAL_GPIO_Init(FMC_A3_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A4_GPIO_PIN; HAL_GPIO_Init(FMC_A4_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A5_GPIO_PIN; HAL_GPIO_Init(FMC_A5_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A6_GPIO_PIN; HAL_GPIO_Init(FMC_A6_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A7_GPIO_PIN; HAL_GPIO_Init(FMC_A7_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A8_GPIO_PIN; HAL_GPIO_Init(FMC_A8_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A9_GPIO_PIN; HAL_GPIO_Init(FMC_A9_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A10_GPIO_PIN; HAL_GPIO_Init(FMC_A10_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A11_GPIO_PIN; HAL_GPIO_Init(FMC_A11_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_A12_GPIO_PIN; HAL_GPIO_Init(FMC_A12_GPIO_PORT, &GPIO_InitStructure); /*数据信号线 针对引脚配置*/ GPIO_InitStructure.Pin = FMC_D0_GPIO_PIN; HAL_GPIO_Init(FMC_D0_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D1_GPIO_PIN; HAL_GPIO_Init(FMC_D1_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D2_GPIO_PIN; HAL_GPIO_Init(FMC_D2_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D3_GPIO_PIN; HAL_GPIO_Init(FMC_D3_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D4_GPIO_PIN; HAL_GPIO_Init(FMC_D4_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D5_GPIO_PIN; HAL_GPIO_Init(FMC_D5_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D6_GPIO_PIN; HAL_GPIO_Init(FMC_D6_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D7_GPIO_PIN; HAL_GPIO_Init(FMC_D7_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D8_GPIO_PIN; HAL_GPIO_Init(FMC_D8_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D9_GPIO_PIN; HAL_GPIO_Init(FMC_D9_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D10_GPIO_PIN; HAL_GPIO_Init(FMC_D10_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D11_GPIO_PIN; HAL_GPIO_Init(FMC_D11_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D12_GPIO_PIN; HAL_GPIO_Init(FMC_D12_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D13_GPIO_PIN; HAL_GPIO_Init(FMC_D13_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D14_GPIO_PIN; HAL_GPIO_Init(FMC_D14_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D15_GPIO_PIN; HAL_GPIO_Init(FMC_D15_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D16_GPIO_PIN; HAL_GPIO_Init(FMC_D16_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D17_GPIO_PIN; HAL_GPIO_Init(FMC_D17_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D18_GPIO_PIN; HAL_GPIO_Init(FMC_D18_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D19_GPIO_PIN; HAL_GPIO_Init(FMC_D19_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D20_GPIO_PIN; HAL_GPIO_Init(FMC_D20_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D21_GPIO_PIN; HAL_GPIO_Init(FMC_D21_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D22_GPIO_PIN; HAL_GPIO_Init(FMC_D22_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D23_GPIO_PIN; HAL_GPIO_Init(FMC_D23_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D24_GPIO_PIN; HAL_GPIO_Init(FMC_D24_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D25_GPIO_PIN; HAL_GPIO_Init(FMC_D25_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D26_GPIO_PIN; HAL_GPIO_Init(FMC_D26_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D27_GPIO_PIN; HAL_GPIO_Init(FMC_D27_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D28_GPIO_PIN; HAL_GPIO_Init(FMC_D28_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D29_GPIO_PIN; HAL_GPIO_Init(FMC_D29_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D30_GPIO_PIN; HAL_GPIO_Init(FMC_D30_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_D31_GPIO_PIN; HAL_GPIO_Init(FMC_D31_GPIO_PORT, &GPIO_InitStructure); /*控制信号线*/ GPIO_InitStructure.Pin = FMC_CS_GPIO_PIN; HAL_GPIO_Init(FMC_CS_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_BA0_GPIO_PIN; HAL_GPIO_Init(FMC_BA0_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_BA1_GPIO_PIN; HAL_GPIO_Init(FMC_BA1_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_WE_GPIO_PIN; HAL_GPIO_Init(FMC_WE_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_RAS_GPIO_PIN; HAL_GPIO_Init(FMC_RAS_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_CAS_GPIO_PIN; HAL_GPIO_Init(FMC_CAS_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_CLK_GPIO_PIN; HAL_GPIO_Init(FMC_CLK_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_CKE_GPIO_PIN; HAL_GPIO_Init(FMC_CKE_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_UDQM_GPIO_PIN; HAL_GPIO_Init(FMC_UDQM_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_LDQM_GPIO_PIN; HAL_GPIO_Init(FMC_LDQM_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_UDQM2_GPIO_PIN; HAL_GPIO_Init(FMC_UDQM2_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.Pin = FMC_LDQM2_GPIO_PIN; HAL_GPIO_Init(FMC_LDQM2_GPIO_PORT, &GPIO_InitStructure); } /** * @brief 对SDRAM芯片进行初始化配置 * @param None. * @retval None. */ static void SDRAM_InitSequence(void) { uint32_t tmpr = 0; /* Step 1 ----------------------------------------------------------------*/ /* 配置命令:开启提供给SDRAM的时钟 */ Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; Command.CommandTarget = FMC_COMMAND_TARGET_BANK; Command.AutoRefreshNumber = 1; Command.ModeRegisterDefinition = 0; /* 发送配置命令 */ HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT); /* Step 2: 延时100us */ SDRAM_delay(1); /* Step 3 ----------------------------------------------------------------*/ /* 配置命令:对所有的bank预充电 */ Command.CommandMode = FMC_SDRAM_CMD_PALL; Command.CommandTarget = FMC_COMMAND_TARGET_BANK; Command.AutoRefreshNumber = 1; Command.ModeRegisterDefinition = 0; /* 发送配置命令 */ HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT); /* Step 4 ----------------------------------------------------------------*/ /* 配置命令:自动刷新 */ Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; Command.CommandTarget = FMC_COMMAND_TARGET_BANK; Command.AutoRefreshNumber = 8; Command.ModeRegisterDefinition = 0; /* 发送配置命令 */ HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT); /* Step 5 ----------------------------------------------------------------*/ /* 设置sdram寄存器配置 */ tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | SDRAM_MODEREG_CAS_LATENCY_3 | SDRAM_MODEREG_OPERATING_MODE_STANDARD | SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; /* 配置命令:设置SDRAM寄存器 */ Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; Command.CommandTarget = FMC_COMMAND_TARGET_BANK; Command.AutoRefreshNumber = 1; Command.ModeRegisterDefinition = tmpr; /* 发送配置命令 */ HAL_SDRAM_SendCommand(&sdramHandle, &Command, SDRAM_TIMEOUT); /* Step 6 ----------------------------------------------------------------*/ /* 设置刷新计数器 */ /* 刷新周期=64ms/8192行=7.8125us */ /* COUNT=(7.8125us x Freq) - 20 */ /* 设置自刷新速率 */ HAL_SDRAM_ProgramRefreshRate(&sdramHandle, 824); } /** * @brief 初始化配置使用SDRAM的FMC及GPIO接口, * 本函数在SDRAM读写操作前需要被调用 * @param None * @retval None */ void SDRAM_Init(void) { //使能GPIO口时钟 RCC->AHB4ENR |= 0x1FC; //配置端口C、D、E、F、G、H、I相应的引脚为复用推挽输出 GPIOC->MODER = 0xFFFFFFFE; GPIOC->OTYPER = 0; GPIOC->OSPEEDR = 0x00000003; GPIOC->PUPDR = 0x00000001; GPIOC->AFR[0] = 0x0000000C; GPIOD->MODER = 0xAFEAFFFA; GPIOD->OTYPER = 0; GPIOD->OSPEEDR = 0xF03F000F; GPIOD->PUPDR = 0x50150005; GPIOD->AFR[0] = 0x000000CC; GPIOD->AFR[1] = 0xCC000CCC; GPIOE->MODER = 0xAAAABFFA; GPIOE->OTYPER = 0; GPIOE->OSPEEDR = 0xFFFFC00F; GPIOE->PUPDR = 0x55554005; GPIOE->AFR[0] = 0xC00000CC; GPIOE->AFR[1] = 0xCCCCCCCC; GPIOF->MODER = 0xAABFFAAA; GPIOF->OTYPER = 0; GPIOF->OSPEEDR = 0xFFC00FFF; GPIOF->PUPDR = 0x55400555; GPIOF->AFR[0] = 0x00CCCCCC; GPIOF->AFR[1] = 0xCCCCC000; GPIOG->MODER = 0xBFFEFAEA; GPIOG->OTYPER = 0; GPIOG->OSPEEDR = 0xC0030F3F; GPIOG->PUPDR = 0x40010515; GPIOG->AFR[0] = 0x00CC0CCC; GPIOG->AFR[1] = 0xC000000C; GPIOH->MODER = 0xAAAAAFFF; GPIOH->OTYPER = 0; GPIOH->OSPEEDR = 0xFFFFF000; GPIOH->PUPDR = 0x55555000; GPIOH->AFR[0] = 0xCC000000; GPIOH->AFR[1] = 0xCCCCCCCC; GPIOI->MODER = 0xFFEBAAAA; GPIOI->OTYPER = 0; GPIOI->OSPEEDR = 0x003CFFFF; GPIOI->PUPDR = 0x00145555; GPIOI->AFR[0] = 0xCCCCCCCC; GPIOI->AFR[1] = 0x00000CC0; // //使能PLL2R // RCC->PLLCFGR |= (1 << 21); // //禁用PLL2 // RCC->CR &= ~(1 << 26); // RCC->PLLCKSELR |= (5 << 12); // RCC->PLL2DIVR = 0x0201028F; // RCC->PLLCFGR |= (2<<6); // RCC->PLLCFGR &= ~(1<<5); // RCC->CR |= (1 << 26); // while(!(RCC->CR&(1<<27))); //RCC->D1CCIPR |= (1<<0); //使能FMC时钟 RCC->AHB3ENR |= (1 << 12); FMC_SDRAM_DEVICE->SDCR[0] = 0x00003AD0; FMC_SDRAM_DEVICE->SDCR[1] = 0x000001E9; FMC_SDRAM_DEVICE->SDTR[0] = 0x0F1F7FFF; FMC_SDRAM_DEVICE->SDTR[1] = 0x01010471; FMC_Bank1_R->BTCR[0] |= 0x80000000; /* Step 1 ----------------------------------------------------------------*/ /* 配置命令:开启提供给SDRAM的时钟 */ FMC_SDRAM_DEVICE->SDCMR = 0x00000009; while((FMC_SDRAM_DEVICE->SDSR&(1<<5))); /* Step 2: 延时100us */ SDRAM_delay(1); /* Step 3 ----------------------------------------------------------------*/ /* 配置命令:对所有的bank预充电 */ FMC_SDRAM_DEVICE->SDCMR = 0x0000000A; while((FMC_SDRAM_DEVICE->SDSR&(1<<5))); /* Step 4 ----------------------------------------------------------------*/ /* 配置命令:自动刷新 */ FMC_SDRAM_DEVICE->SDCMR = 0x000000EB; while((FMC_SDRAM_DEVICE->SDSR&(1<<5))); /* Step 5 ----------------------------------------------------------------*/ /* 设置sdram寄存器配置 */ FMC_SDRAM_DEVICE->SDCMR =0x0004600C; while((FMC_SDRAM_DEVICE->SDSR&(1<<5))); /* Step 6 ----------------------------------------------------------------*/ /* 设置自刷新速率 */ FMC_SDRAM_DEVICE->SDRTR |= (1855<<1); } /** * @brief 以“字”为单位向sdram写入数据 * @param pBuffer: 指向数据的指针 * @param uwWriteAddress: 要写入的SDRAM内部地址 * @param uwBufferSize: 要写入数据大小 * @retval None. */ void SDRAM_WriteBuffer(uint32_t* pBuffer, uint32_t uwWriteAddress, uint32_t uwBufferSize) { __IO uint32_t write_pointer = (uint32_t)uwWriteAddress; /* 禁止写保护 */ HAL_SDRAM_WriteProtection_Disable(&hsdram1); /* 检查SDRAM标志,等待至SDRAM空闲 */ while(HAL_SDRAM_GetState(&hsdram1) != RESET) { } /* 循环写入数据 */ for (; uwBufferSize != 0; uwBufferSize--) { /* 发送数据到SDRAM */ *(uint32_t *) (SDRAM_BANK_ADDR + write_pointer) = *pBuffer++; /* 地址自增*/ write_pointer += 4; } } /** * @brief 从SDRAM中读取数据 * @param pBuffer: 指向存储数据的buffer * @param ReadAddress: 要读取数据的地十 * @param uwBufferSize: 要读取的数据大小 * @retval None. */ void SDRAM_ReadBuffer(uint32_t* pBuffer, uint32_t uwReadAddress, uint32_t uwBufferSize) { __IO uint32_t write_pointer = (uint32_t)uwReadAddress; /* 检查SDRAM标志,等待至SDRAM空闲 */ while ( HAL_SDRAM_GetState(&hsdram1) != RESET) { } /*读取数据 */ for(; uwBufferSize != 0x00; uwBufferSize--) { *pBuffer++ = *(__IO uint32_t *)(SDRAM_BANK_ADDR + write_pointer ); /* 地址自增*/ write_pointer += 4; } } /** * @brief 测试SDRAM是否正常 * @param None * @retval 正常返回1,异常返回0 */ uint8_t SDRAM_Test(void) { /*写入数据计数器*/ uint32_t counter=0; /* 8位的数据 */ uint8_t ubWritedata_8b = 0, ubReaddata_8b = 0; /* 16位的数据 */ uint16_t uhWritedata_16b = 0, uhReaddata_16b = 0; SDRAM_INFO("正在检测SDRAM,以8位、16位的方式读写sdram..."); /*按8位格式读写数据,并校验*/ /* 把SDRAM数据全部重置为0 ,SDRAM_SIZE是以8位为单位的 */ for (counter = 0x00; counter < SDRAM_SIZE; counter++) { *(__IO uint8_t*) (SDRAM_BANK_ADDR + counter) = (uint8_t)0x0; } /* 向整个SDRAM写入数据 8位 */ for (counter = 0; counter < SDRAM_SIZE; counter++) { *(__IO uint8_t*) (SDRAM_BANK_ADDR + counter) = (uint8_t)(ubWritedata_8b + counter); } /* 读取 SDRAM 数据并检测*/ for(counter = 0; counter