因为工作项目需求,需要使用STM32与FPGA通信进行联合开发,两者通信,自然首选STM32自带的FSMC通信接口。为了搞清楚FSMC的时序与寻址细节,特使用逻辑分析仪对FSMC的8位、16位、32位数据写操作进行了抓取分析,从而得到了FSMC的时序与寻址细节。时间匆忙,少了很多废话的部分,具体的后面再完善吧,具体意图见本文标题。腰好痛啊,最近身体和大脑一直超负荷运转,是该出去转转,出去运动运动了。 8位操作方式:对地址65534写8位的数i代码 *(vu8*)(Bank1_SRAM3_ADDR+65534)=i;
i++;
|
对地址65534写8位的数i时序波形 对地址65535写8位的数i代码 *(vu8*)(Bank1_SRAM3_ADDR+65534)=i;
i++;
|
对地址65535写8位的数i时序波形 STM32通过FSMC写8位数据:C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为: FSMC_ADDR = C_Addr/2 FSMC_LB = C_Addr%2 FSMC_UB =~ (C_Addr%2) 16位操作方式:对地址65534写16位的数6555代码 *(vu16*)(Bank1_SRAM3_ADDR+65534)=6555;
|
对地址65534写16位的数6555时序波形 
对地址65535写16位的数6555代码 *(vu16*)(Bank1_SRAM3_ADDR+65535)=6555;
|
对地址65535写16位的数6555时序波形 STM32通过FSMC写16位数据:C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为: 如果C_Addr为偶数,则 FSMC_ADDR = C_Addr/2 FSMC_LB = FSMC_UB = 0; FSMC一次性即可完成16位数据的写入。 如果C_Addr为奇数,则实际FSMC会将数据分成两个8位的数据来进行操作,因此效率会低很多。 先写C_Addr,写入数据字节为待写入数据的高字节 FSMC_ADDR = C_Addr/2 FSMC_LB =1; FSMC_UB =0; 然后写C_Addr + 1地址,写入数据字节为待写入数据的低字节 FSMC_ADDR = (C_Addr + 1) /2 FSMC_LB =0; FSMC_UB =1; 32位操作方式:对地址65534写32位的数1265536(0x134F80)代码 *(vu32*)(Bank1_SRAM3_ADDR+65534)= 1265536;
|
对地址65534写32位的数0x134F80时序波形 对地址65535写32位的数1265536(0x134F80)代码 *(vu32*)(Bank1_SRAM3_ADDR+65535)= 1265536;
|
对地址65535写32位的数0x134F80时序波形 对地址65536写32位的数1265536(0x134F80)代码 *(vu32*)(Bank1_SRAM3_ADDR+65536)= 1265536;
|
对地址65536写32位的数0x134F80时序波形 对地址65537写32位的数1265536(0x134F80)代码 *(vu32*)(Bank1_SRAM3_ADDR+65537)= 1265536;
|
对地址65537写32位的数0x134F80时序波形 STM32通过FSMC写32位数据:C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的起始地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为: 如果C_Addr为4的倍数,则FSMC首先在起始地址处写入待写入数据的低字节和次低字节: FSMC_ADDR = C_Addr/2 FSMC_LB = FSMC_UB = 0; 然后FSMC再在起始地址+2处写入待写入数据的低字节和次低字节: FSMC_ADDR = (C_Addr+2)/2 FSMC_LB = FSMC_UB = 0; 只需要两次16位数据写入操作即可完成一个32位数据的写入,因此效率较高。 如果C_Addr为奇数,则实际FSMC会将数据分成两个8位的数据和一个16位的数据来进行操作,需要3次写入操作才能完成32位数据的写入(效率较低)。 FSMC首先在起始地址(C_Addr)位置以8位写入方式写入待写入数据的低字节: FSMC_ADDR = C_Addr/2 FSMC_LB = 1; FSMC_UB = 0; 然后FSMC再在起始地址+2处(C_Addr + 2)以16位数据方式写入带写入数据的次低字节和次高字节: FSMC_ADDR = (C_Addr+2)/2 FSMC_LB = FSMC_UB = 0; 最后FSMC再在起始地址+4处(C_Addr + 2)以8位写入方式写入待写入数据的高字节: FSMC_ADDR = (C_Addr+4)/2 FSMC_LB = 0; FSMC_UB = 1; 小梅哥FPGA设计思想与验证方法教程系列文档
2015年07月10号于Snow Dream电子工作室
|