I've been able to connect SDRAM IC MT48LC4M32B2 to STM32F767 Nucleo bord and configure FMC to read and write to SDRAM. I'd like to check for actual capacity of my SDRAM chip. But can't figure how many of that 32bit words can be stored in IC. And how to detect end of aviable space? Here is my code for writing and reading:
#define BUFFER_SIZE ((uint32_t)0x1000)
#define WRITE_READ_ADDR ((uint32_t)0x800)
Fill_Buffer(aTxBuffer, BUFFER_SIZE, 0x55555555);
/* Write data to the SDRAM memory */
for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
{
*(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex) = aTxBuffer[uwIndex];
}
/* Read back data from the SDRAM memory */
for (uwIndex = 0; uwIndex < BUFFER_SIZE; uwIndex++)
{
aRxBuffer[uwIndex] = *(__IO uint32_t*) (SDRAM_BANK_ADDR + WRITE_READ_ADDR + 4*uwIndex);
}
/*##-3- Checking data integrity ############################################*/
for (uwIndex = 0; (uwIndex < BUFFER_SIZE); uwIndex++)
{
if (aRxBuffer[uwIndex] != aTxBuffer[uwIndex])
{
uwWriteReadStatus++; //error counter
badByte[uwIndex] = 1;
}
}
static void Fill_Buffer(uint32_t *pBuffer, uint32_t uwBufferLenght, uint32_t uwOffset)
{
uint32_t tmpIndex = 0;
/* Put in global buffer different values */
for (tmpIndex = 0; tmpIndex < uwBufferLenght; tmpIndex++ )
{
pBuffer[tmpIndex] = uwOffset;
uwOffset = ~uwOffset;
}
}
A typical approach relies on the fact that the value stored at one past the size of the memory will be the same as the value stored at address 0x0
. This is because the higher-order bits of the address are not decoded, so you get "another" copy of your SDRAM at that address.
You can store an "unusual" value at address 0x0
, then make a loop to repeatedly double a guess of what the memory size is, until you find the repeated value.
Some completely untested code, that hopefully shows the idea:
#define MAGIC_VAL (0xdeadbeef)
uint32_t check_sdram_size(void)
{
uint32_t *zero = (uint32_t *) (SDRAM_BANK_ADDR);
*zero = MAGIC_VAL;
uint32_t test_size;
for (test_size = 1024u ; ; test_size *= 2u)
{
uint32_t *check = (uint32_t *) (SDRAM_BANK_ADDR + test_size);
if (*check == MAGIC_VAL)
break;
}
return test_size;
}
This starts by guessing that the memory is just 1024 bytes. If you know it will definitely be bigger than that, you can put in a more sensible starting guess.
This will only work if your MCU will actually try to perform a transaction on addresses above the size of the SDRAM. Presumably you'll have configured some kind of maximum size for the SDRAM in the MCU, so you'd want to stop your loop if you reached that, and assume that you have a maximally sized SDRAM.