2017-11-14 07:24 AM
Hello
I'm using the FMC bus on a STM32F767 to read and write to an external device in SRAM mode with 32-Bit width.
Is it not possible to address the external memory in byte-address mode instead of 32-bit address mode?
I measured the address signals (A3-A0) and these signals are always shiftet right by two bits from the address I use in Code. Following examples:
External Memory at Address 0x60000000 (FMC Bank 1, NOR/PSRAM 1)
reading address 0x60000000 - Address Bus measured at external memory (A3-A0): 0x00
reading address 0x60000001 - Address Bus measured (A3-A0): 0x00
reading address 0x60000002 - Address Bus measured (A3-A0): 0x00
reading address 0x60000003 - Address Bus measured (A3-A0): 0x00
reading address 0x60000004 - Address Bus measured (A3-A0): 0x01
reading address 0x60000005 - Address Bus measured (A3-A0): 0x01
reading address 0x60000006 - Address Bus measured (A3-A0): 0x01
reading address 0x60000007 - Address Bus measured (A3-A0): 0x01
reading address 0x60000008 - Address Bus measured (A3-A0): 0x02
As I understand, I have to read 4 bytes at address 0x00, and the next 4 bytes at address 0x01. But most memories are byte-addressed I thought, so byte 0 at address 0x00, byte 1 at address 0x01 and so on.
During read the BLE0-3 are always set to LOW. These signals are only used when writing.
Another question is, how to read as example 6 bytes at adress 0x00?
By using HAL_SRAM_Read_32b() it is only possible to read multiplication of 4 bytes. Do I have to use HAL_SRAM_Read_32b() for the first 4 bytes and then HAL_SRAM_Read_16b() for the remaining 2 bytes?
Or is it better to read 8 bytes with HAL_SRAM_Read_32b() and then discard the 2 bytes which I not use manually?
Thank you for any help.
Dani
2017-11-14 07:34 AM
>>
As I understand, I have to read 4 bytes at address 0x00, and the next 4 bytes at address 0x01. But most memories are byte-addressed I thought, so byte 0 at address 0x00, byte 1 at address 0x01 and so on.
At the bus level perhaps, ie address bits exposed to the physical device. In the memory map the first 32-bit word is at 0x60000000, the second at 0x60000004
When reading, all 32-bit are presented on the data bus, as there is no cost to doing so, the bus management hardware extracts the byte(s) it wants, figure a byte level barrel shifter or mux. A read of six bytes will need 2 bus transactions, depending on the alignment you then cherry pick the bytes you want. The processor doesn't have a native 6-byte read instruction, you can emulate this by doing an aligned LDRD into two registers (64-bit load), and then shifting.
2017-11-14 08:56 AM
I tried to read 4 bytes at address 0x0x60000000, and the next 4 bytes at address 0x60000004.
The result is I have always the same result from address 0x60000000 - 0x6000000C. At address 0x60000010 is the result I expect at address 0x60000004.
So I have to increment the address pointer always by 0x10 to get the next 4 bytes. Is this the normal way or how to do it else?
So if I want only 6 bytes at address 0x0x60000000, I call the following code (there are 3 16-bit variables I want to read):
uint16_t rxBuffer[4];
HAL_SRAM_Read_32b(&sram_Handle, (uint32_t *)0x0x60000000, (uint32_t *)rxBuffer, 2);
void HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer, uint32_t BufferSize)
{ /* Read data from memory */ for(; BufferSize != 0; BufferSize--) { *pDstBuffer = *(__IO uint32_t *)pAddress; pDstBuffer++; pAddress++; }}
And then I only use rxBuffer[0] - rxBuffer[2] and discarding rxBuffer[3]? Or how is the bus management hardware extracting these bytes I dont need?
I mean I can't do the following:
uint16_t rxBuffer[3];
HAL_SRAM_Read_32b(&sram_Handle, (uint32_t *)0x0x60000000, (uint32_t *)rxBuffer, 2);
because the last 2 bytes read from SRAM are then anywhere in my code at the address following rxBuffer[2].
2017-11-14 09:45 AM
>>
The result is I have always the same result from address 0x60000000 - 0x6000000C. At address 0x60000010 is the result I expect at address 0x60000004.
This would suggest the bus isn't configured correctly.
volatile uint32_t *p = (
volatile uint32_t *)0x60000000
;int i;
uint32_t d = 0x11121314;
for(i=0;i<8; i++)
{
*p = d;
printf('%p %08lx\n', p, d);
p++;
d += 0x11111111;
}
putchar('\n');
for(i=0; i<8; i++)
{
printf('%p %08lX\n', p, *p); // Address and content
p++;
}
putchar('\n');
If the two passes here don't display the same data you have some hardware/configuration issue.
A0 at the STM32 package pins should be bit 2 from the internal address bus in 32-bit data mode. ie the hardware in the STM32 shifts the address bits based on the width of the transaction settings for the bus, not your 8/16/32-bit read/write at the code level.
2017-11-14 09:48 AM
60000000 11121314
60000004 2223242560000008 333435366000000C 4445464760000010 5556575860000014 6667686960000018 7778797A6000001C 88898A8B60000000 11121314
60000004 2223242560000008 333435366000000C 4445464760000010 5556575860000014 6667686960000018 7778797A6000001C 88898A8B2017-11-15 01:27 AM
2018-04-15 04:32 AM
This issue probably has been resolved, see