2019-04-03 07:22 AM
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.
2019-04-04 10:06 AM
It works perfectly when using words though, so how could it be pin related?
2019-04-05 08:02 AM
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 :
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?
2019-04-05 08:44 AM
Because your data bus is all muddled up. The byte positions don't match up with the signals.
2019-04-05 08:54 AM
Yes, going through it now, the byte positions are muddled up.
Bit reversal within the byte would be tolerable, probably, but the byte lane signals would need to map properly, and the bits here don't map well
As I see it D0..D7 on schematic map to D27, D2, D3, D28, D29, D26, D30, D31 (mix of lane 3 and lane 0)
At a bit level I think this will impact the config words written also
2019-04-05 09:09 AM
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
2020-10-30 08:40 AM
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.