Skip to main content
michaelmichael9137
Associate III
April 3, 2019
Question

STM32F7 and Extern SDRAM Bank Accessing Problem

  • April 3, 2019
  • 8 replies
  • 4686 views

Hi everyone,

I'm using a STM32F769BGT6 with an external SDRAM (IS42S32400F). This SDRAM is composed of 4 banks. Each bank contains 12 Rows (4096), 8 Columns (256), and each cell is 32 bits. So : 4096*256*32 = 33 554 432 bits, or 4MBytes/Bank. That means that it can store 4x1M uint32 variables.

I've done the configuration in system_stm32f7xx.c, because i need to use it as a memory section. Here is the initialization code :

void SystemInit_ExtMemCtl(void)
{
 __IO uint32_t tmp = 0;
 
 register uint32_t tmpreg = 0, timeout = 0xFFFF;
 register uint32_t index;
 
 /* Enable GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
 RCC->AHB1ENR |= 0x000001F8;
 
 /* Delay after an RCC peripheral clock enabling */
 tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOEEN);
 
 /* Connect PDx pins to FMC Alternate function */
 GPIOD->AFR[0] = 0x000000CC;
 GPIOD->AFR[1] = 0xCC000CCC;
 /* Configure PDx pins in Alternate function mode */ 
 GPIOD->MODER = 0xA02A000A;
 /* Configure PDx pins speed to 100 MHz */ 
 GPIOD->OSPEEDR = 0xF03F000F;
 /* Configure PDx pins Output type to push-pull */ 
 GPIOD->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PDx pins */ 
 GPIOD->PUPDR = 0x50150005;
 
 /* Connect PEx pins to FMC Alternate function */
 GPIOE->AFR[0] = 0xC00000CC;
 GPIOE->AFR[1] = 0xCCCCCCCC;
 /* Configure PEx pins in Alternate function mode */ 
 GPIOE->MODER = 0xAAAA800A;
 /* Configure PEx pins speed to 100 MHz */ 
 GPIOE->OSPEEDR = 0xFFFFC00F;
 /* Configure PEx pins Output type to push-pull */ 
 GPIOE->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PEx pins */ 
 GPIOE->PUPDR = 0x55554005;
 
 /* Connect PFx pins to FMC Alternate function */
 GPIOF->AFR[0] = 0x00CCCCCC;
 GPIOF->AFR[1] = 0xCCCCC000;
 /* Configure PFx pins in Alternate function mode */ 
 GPIOF->MODER = 0xAA800AAA;
 /* Configure PFx pins speed to 100 MHz */ 
 GPIOF->OSPEEDR = 0xFFC00FFF;
 /* Configure PFx pins Output type to push-pull */ 
 GPIOF->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PFx pins */ 
 GPIOF->PUPDR = 0x55400555;
 
 /* Connect PGx pins to FMC Alternate function */
 GPIOG->AFR[0] = 0x00CC00CC;
 GPIOG->AFR[1] = 0xC000000C;
 /* Configure PGx pins in Alternate function mode */ 
 GPIOG->MODER = 0x80020A0A;
 /* Configure PGx pins speed to 100 MHz */ 
 GPIOG->OSPEEDR = 0xC0030F0F;
 /* Configure PGx pins Output type to push-pull */ 
 GPIOG->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PGx pins */ 
 GPIOG->PUPDR = 0x40010505;
 
 /* Connect PHx pins to FMC Alternate function */
 GPIOH->AFR[0] = 0x00C0CC00;
 GPIOH->AFR[1] = 0xCCCCCCCC;
 /* Configure PHx pins in Alternate function mode */ 
 GPIOH->MODER = 0xAAAA08A0;
 /* Configure PHx pins speed to 100 MHz */ 
 GPIOH->OSPEEDR = 0xFFFF0CF0;
 /* Configure PHx pins Output type to push-pull */ 
 GPIOH->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PHx pins */ 
 GPIOH->PUPDR = 0x55550450;
 
 /* Connect PIx pins to FMC Alternate function */
 GPIOI->AFR[0] = 0xCCCCCCCC;
 GPIOI->AFR[1] = 0x00000CC0;
 /* Configure PIx pins in Alternate function mode */ 
 GPIOI->MODER = 0x0028AAAA;
 /* Configure PIx pins speed to 100 MHz */ 
 GPIOI->OSPEEDR = 0x003CFFFF;
 /* Configure PIx pins Output type to push-pull */ 
 GPIOI->OTYPER = 0x00000000;
 /* No pull-up, pull-down for PIx pins */ 
 GPIOI->PUPDR = 0x00145555;
 
/*-- FMC Configuration ------------------------------------------------------*/
 /* Enable the FMC interface clock */
 RCC->AHB3ENR |= 0x00000001;
 // FMC_Bank5_6->MWID = 0x
 /* Delay after an RCC peripheral clock enabling */
 tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
 
 /* Configure and enable SDRAM bank1 */
 FMC_Bank5_6->SDCR[0] = 0x00001BE4;
 FMC_Bank5_6->SDTR[0] = 0x01115361;
 
 /* SDRAM initialization sequence */
 /* Clock enable command */
 FMC_Bank5_6->SDCMR = 0x00000011; 
 tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
 while((tmpreg != 0) && (timeout-- > 0))
 {
 tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
 }
 
 /* Delay */
 for (index = 0; index<1000; index++);
 
 /* PALL command */
 FMC_Bank5_6->SDCMR = 0x00000012; 
 timeout = 0xFFFF;
 while((tmpreg != 0) && (timeout-- > 0))
 {
 tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
 }
 
 /* Auto refresh command */
 FMC_Bank5_6->SDCMR = 0x000000F3;
 timeout = 0xFFFF;
 while((tmpreg != 0) && (timeout-- > 0))
 {
 tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
 }
 
 /* MRD register program */
 FMC_Bank5_6->SDCMR = 0x00046014;
 timeout = 0xFFFF;
 while((tmpreg != 0) && (timeout-- > 0))
 {
 tmpreg = FMC_Bank5_6->SDSR & 0x00000020; 
 } 
 
 /* Set refresh count */
 tmpreg = FMC_Bank5_6->SDRTR;
 FMC_Bank5_6->SDRTR = (tmpreg | (0x00000603<<1));
 
 /* Disable write protection */
 tmpreg = FMC_Bank5_6->SDCR[0];
 FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
 
 /*
 * Disable the FMC bank1 (enabled after reset).
 * This, prevents CPU speculation access on this bank which blocks the use of FMC during
 * 24us. During this time the others FMC master (such as LTDC) cannot use it!
 */
 FMC_Bank1->BTCR[0] = 0x000030d2;
 
 (void)(tmp);
}

On line 94 of this code snippet, you can see this value for SDCR register :

FMC_Bank5_6->SDCR[0] = 0x00001BE4;

The "B" means that I chose a Memory Data Bus Width of 32 bits.

I made a modification in the linker to add a memory section like follows :

/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
SDRAM (xrw) : ORIGIN = 0xC0000000, LENGTH = 16M
}
 
/* Define output sections */
SECTIONS
{
 /* Section créée pour l'allocation dans la SDRAM externe*/
 .masection :
 {
 . = ALIGN(4);
 *(.masection) 
 *(.masection*)
 . = ALIGN(4);
 } >SDRAM

The following code, in the main.c, tests that I can write in the entire memory :

const uint32_t testSize2 = 4000000;
 
uint32_t volatile memoryTest2[testSize2] __attribute__((section(".masection")));
 
 for(size_t i = 0; i < testSize2; i++)
 {
 memoryTest2[i] = i;
 }
 
 for(size_t i = 0; i < testSize2; i++)
 {
 if(memoryTest2[i] != i) __DEBUG_BKPT();
 }

It creates a tab of 4M uint32, and works perfectly.

Sorry for the long intro, but I wanted this to be very clear for you and for myself.

Now my question is :

I need to use a Memory Data Bus Width of 8 bits, instead of 32, because I will use this memory section exclusively with 8 bits words.

For this, I simply changed FMC_Bank5_6->SDCR[0] = 0x00001CE4;

Now, I cannot create a tab of 4M uint32t anymore, I'm limited to 1M. If I try to add more, I have a hardfault. I have the feeling that the low level FMC drivers are not dealing with 8 bits data width properly.

This is very frustrating because 1/4 of my memory is not accessible and I'm stuck.

If anyone has an idea on this, it would be great!

Thanks for your time.

This topic has been closed for replies.

8 replies

Tesla DeLorean
Guru
April 3, 2019

>>I need to use a Memory Data Bus Width of 8 bits, instead of 32, because I will use this memory section exclusively with 8 bits words.

WHY?

Doesn't the interface support BYTE LANES?

>> If I try to add more, I have a hardfault.

Yeah, no kidding. The memory region is constrained via rows/columns/width, it is like the old 68000, it faults if you access non-existent memory.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
michaelmichael9137
Associate III
April 4, 2019

Hi Clive,

Thanks for the answer.

I figured a few things out reading this post : https://community.st.com/s/question/0D50X00009XkYQCSA3/stm32f407-fsmc-physical-addressing

I noticed two things by re-reading the RM :

0690X0000089vgnQAA.png

Here I see that BM[1:0] is a byte mask for 32-bit access.

And here :

0690X0000089vhRQAQ.png

FMC_NBL[3:0] Seems to be related to my issue as well.

I can't figure out what you mean by BYTE LANES. I assume it is related with what is above. Could you enlighten me a little more?

Here is what I get when I try to write UINT32 elements in SDRAM set to 32b width (Code in my previous post) :

0690X0000089vjNQAQ.png

As you can see, everything's fine.

Now here is the result for a uint8 tab :

0690X0000089vjIQAQ.png

As always, thanks for your time.

michaelmichael9137
Associate III
April 4, 2019

Do i need to do something specific to have those BYTE LANES pins NBL[3:0] to properly mask data when I try to write bytes? I assume it is handled by the FMC, but maybe I have to use exclusively HAL methods to have it working?

Tesla DeLorean
Guru
April 4, 2019

Post initialization the HAL plays no role, it is a configure and forget set up. You have to setup the pins, controller and memory correctly from the outset.

I'm not going to dig through register level code to validate it. My approach would be to use the verbose HAL configuration methods and examples first, and validate the read/write functionality of the SDRAM array at 8, 16 and 32-bit widths. Once that's done I'd migrate to the register level stuff. In the past I've had to do this for a number of DISCO boards because ST only provided code for the EVAL boards.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
April 4, 2019

>>I can't figure out what you mean by BYTE LANES. I assume it is related with what is above. Could you enlighten me a little more?

32-bit wide memories are managed by the bus controller and CPU, where a barrel shifter gets bytes written to memory in the right position across the 32-bit word, and then instructs the memory to take specific byte(s) from the presented data. This is also used with you have unaligned 32-bit writes that span two different 32-bit memory locations. ie (addr & 3) != 0

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0203f/I1044275.html

Is this a custom board constructed yourself? What is the pinning?

I would go with a 50 MHz "speed" settings, the slew rate here is a bit aggressive for short traces without series resistors.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
michaelmichael9137
Associate III
April 4, 2019

Thanks for the link, much clearer now.

The board is custom yes.

Here is the pinout :

0690X0000089zvrQAA.png

0690X0000089zwBQAQ.png

And here is what the length matched traces look like:

0690X0000089vwCQAQ.png

Tesla DeLorean
Guru
April 4, 2019

The pin diagrams here are unreadably small/low-res

Test your memory read/write 32/8-bit code on an STM32F769I-DISCO, see that they work properly there, where the width is managed transparently.

Create your own long-hand form of the HAL's BSP SDRAM code like that for the DISCO, but for your own board. STM32Cube_FW_F7_V1.15.0\Drivers\BSP\STM32F769I-Discovery\stm32f769i_discovery_sdram.c

All the SDRAM settings need to be coherent across the controller, and SDRAM configuration writes.

Set aside your desire to get the SDRAM working at startup, and validate it first using the later stage HAL method.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
michaelmichael9137
Associate III
April 5, 2019

Hi Clive,

Ok I tested the DISCO code, with proper conf for my board, and the behaviour is exactly the same. It's working for 32 bit, but not for 8 bit.

I updated the schematics from my previous post with more hi-res files, sorry about that.

I noticed something when checking the pinout :

0690X0000089zwaQAA.png

The three first columns are what I actually have wired on the PCB. You can see that the third block of eight pins (DQ16 : DQ23) are reversed.

I also noticed that none of the data pins are wired on the GPIO like indicated on the reference manual (last column).

Could it have an impact on the outcome of my read/write attempts?

michaelmichael9137
Associate III
April 4, 2019

I set SDCLK to the minimum (3xHCLK periods) and CAS latency to the max to avoid timing problems but results in my tab are the same than before.

Tesla DeLorean
Guru
April 4, 2019

Suggests a more pin level issue. Figure several hours of work to unravel

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
michaelmichael9137
Associate III
April 4, 2019

It works perfectly when using words though, so how could it be pin related?

Tesla DeLorean
Guru
April 5, 2019

Because your data bus is all muddled up. The byte positions don't match up with the signals.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
April 5, 2019
BOARD PIN STM32F769
 
D0 PI3 D27
D1 PD0 D2
D2 PD1 D3
D3 PI6 D28
D4 PI7 D29
D5 PI2 D26
D6 PI9 D30
D7 PI10 D31
 
D8 PD10 D15
D9 PD14 D0
D10 PD15 D1
D11 PH13 D21
D12 PH14 D22
D13 PH15 D23
D14 PI0 D24
D15 PI1 D25
 
D16 PE14 D11
D17 PE13 D10
D18 PE12 D9
D19 PE11 D8
D20 PE10 D7
D21 PE9 D6
D22 PE8 D5
D23 PE7 D4
 
D24 PE15 D12
D25 PH8 D16
D26 PH9 D17
D27 PH10 D18
D28 PH11 D19
D29 PH12 D20
D30 PD8 D13
D31 PD9 D14
 
 
Sorted by STM32 order
 
D9 PD14 D00 LANE 0
D10 PD15 D01
D1 PD0 D02
D2 PD1 D03
D23 PE7 D04
D22 PE8 D05
D21 PE9 D06
D20 PE10 D07
 
D19 PE11 D08 LANE 1
D18 PE12 D09
D17 PE13 D10
D16 PE14 D11
D24 PE15 D12
D30 PD8 D13
D31 PD9 D14
D8 PD10 D15
 
D25 PH8 D16 LANE 2
D26 PH9 D17
D27 PH10 D18
D28 PH11 D19
D29 PH12 D20
D11 PH13 D21
D12 PH14 D22
D13 PH15 D23
 
D14 PI0 D24 LANE 3
D15 PI1 D25
D5 PI2 D26
D0 PI3 D27
D3 PI6 D28
D4 PI7 D29
D6 PI9 D30
D7 PI10 D31

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Lix Paulian
Associate II
October 30, 2020

This is an old thread, I suspect that the issue has been solved in a way or the other. However the correct resolution can be found here:

https://www.keil.com/support/docs/3777.htm

I stumbled on this and I spent almost two days debugging this one. It is an issue with the FMC and misaligned accesses in the SDRAM area (addresses above 0xC0000000). I am adding this post here for those who may have the same problem. There is no mention on this in the STM32Fxx manual. I don't want to detail the possible solutions here (follow the link), however suffice to say that I used the MPU recommendation and it worked perfectly for me.