硬件原理图:
Fsmc 寄存器框图:
从上图可以看出 stm32 的Fsmc 功能 包过 Nandflash、 内存 、PC卡 三部分功能, Nor 存储控制器分为4个块, 每块大小为64M,
(1M—–0x100000, 64M————0X4000000)
0x60000000———————-0x63FFFFFF 第1块
0x64000000———————-0x67FFFFFF 第2块
0x68000000———————-0x6bFFFFFF 第3块
0x6C000000——————–0x70000000 第4 块
当地址在 0x60000000———————-0x63FFFFFF , fsmc 自动选择片选 cs1
当地址在 0x64000000———————-0x67FFFFFF , fsmc 自动选择片选 cs2
当地址在 0x68000000———————-0x6bFFFFFF , fsmc 自动选择片选 cs3
当地址在 0x6C000000——————–0x70000000 , fsmc 自动选择片选 cs4
软件配置:
void FSMC_SRAM_Init(void)
{
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef p;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOG | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
/*-- GPIO Configuration ------------------------------------------------------*/
/* SRAM Data lines configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 |
GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
GPIO_Pin_15;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/* SRAM Address lines configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPIO_Pin_13 |
GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |
GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* NOE and NWE configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* NE3 configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/* NBL0, NBL1 configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_Init(GPIOG, &GPIO_InitStructure);
GPIO_SetBits(GPIOG,GPIO_Pin_9|GPIO_Pin_12);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //复用推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_ResetBits(GPIOE, GPIO_Pin_2);
/*-- FSMC Configuration ------------------------------------------------------*/
p.FSMC_AddressSetupTime = 2;
p.FSMC_AddressHoldTime = 2;
p.FSMC_DataSetupTime = 1;
p.FSMC_BusTurnAroundDuration = 1;
p.FSMC_CLKDivision = 0;
p.FSMC_DataLatency = 0;
p.FSMC_AccessMode = FSMC_AccessMode_A;
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &p;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE); //Enable FSMC Bank1_SRAM Bank
}
#define Bank1_SRAM3_ADDR ((u32)0x68000000)
#define BUFFER_SIZE 0x400
#define WRITE_READ_ADDR 0x400*10
static u16 TxBuffer[BUFFER_SIZE];
static u16 RxBuffer[BUFFER_SIZE];
u32 WriteReadStatus = 0, Index = 0;
/**
* @brief 向SRAM写入指定长度的数据
* @param pBuffer:指向发送缓冲;WriteAddr:写入地址;NumHalfwordToWrite:数据长度
* @retval None
*/
void FSMC_SRAM_WriteBuffer(u16* pBuffer, u32 WriteAddr, u32 NumHalfwordToWrite)
{
for(; NumHalfwordToWrite != 0; NumHalfwordToWrite--) //while there is data to write
{
*(u16 *) (Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer++; // Transfer data to the memory
WriteAddr += 2; //Increment the address
}
}
/**
* @brief 从SRAM读取指定长度的数据
* @param pBuffer:指向读取缓冲;ReadAddr:读取地址;NumHalfwordToRead:数据长度
* @retval None
*/
void FSMC_SRAM_ReadBuffer(u16* pBuffer, u32 ReadAddr, u32 NumHalfwordToRead)
{
for(; NumHalfwordToRead != 0; NumHalfwordToRead--) //while there is data to read
{
*pBuffer++ = *(vu16*) (Bank1_SRAM3_ADDR + ReadAddr); //Read a half-word from the memory
ReadAddr += 2; //Increment the address
}
}
/**
* @brief 填充数据
* @param pBuffer:指向填充缓冲;BufferLenght:数据长度;Offset:开始的数值
* @retval None
*/
void Fill_Buffer(u16 *pBuffer, u16 BufferLenght, u32 Offset)
{
u16 IndexTmp = 0;
for (IndexTmp = 0; IndexTmp < BufferLenght; IndexTmp++ )
{
pBuffer[IndexTmp] = IndexTmp + Offset;
}
}
/**
* @brief SRAM读写测试
* @param None
* @retval None
*/
void SRAM_Test(void)
{
vu32 time1=0,time2=0;
printf("\r\n***********************SRAM读写测试**********************\r\n");
Fill_Buffer(TxBuffer, BUFFER_SIZE, 0x3212);
FSMC_SRAM_WriteBuffer(TxBuffer, WRITE_READ_ADDR, BUFFER_SIZE);//从32k开始写
printf("\r\n写1KB complete/s\r\n" ); //10us中断1次
FSMC_SRAM_ReadBuffer(RxBuffer, WRITE_READ_ADDR, BUFFER_SIZE);
printf("读1k 完成\r\n",(time2-time1)*10,100000/(time2-time1)); //10us中断1次
for(Index = 0x00; (Index < BUFFER_SIZE) && (WriteReadStatus == 0); Index++)//检查内容的正确性
{
if(RxBuffer[Index] != TxBuffer[Index])
{
WriteReadStatus = Index + 1;
}
}
if (WriteReadStatus == 0) //pass
{
printf("\r\nSRAM读写测试通过\r\n");
}
else //error
{
printf("\r\nSRAM读写测试失败,请复位后再试一次\r\n");
}
}
////////////// 连续写10k ,读10k 测试 sram中的数据
int WriteFsmcAddr =0 ;
int ReadFsmcAddr =0 ;
static u16 ReadBuffer[2048];
u16 readdata;
int errtest=0;
void SramTestByLxl(void)
{
for( WriteFsmcAddr =0; WriteFsmcAddr <1024*10;WriteFsmcAddr+=2) //while there is data to write
{
*(u16 *) (Bank1_SRAM3_ADDR + WriteFsmcAddr) = 0x5678; // Transfer data to the memory
}
printf("写10k 数据完成 \r\n");
for( ReadFsmcAddr =0; ReadFsmcAddr <1024*10;ReadFsmcAddr+=2) //while there is data to write
{
readdata = *(vu16*) (Bank1_SRAM3_ADDR + ReadFsmcAddr);
if(readdata !=0x5678)
{
printf("read addr %d err,val is %x",ReadFsmcAddr,readdata);
errtest++;
}
}
if(errtest==0)
{
printf("读10k 数据都正确 \r\n");
}
printf("SramTestByLxl 执行完成 \r\n");
}