2015-08-17 02:39 PM
I'm new to ARM microcontrollers, and having a bit of trouble understanding something. I have an LCD with the SSD1963 controller and external SRAM (AS6C1616) connected in parallel using the FSMC. The SSD1963 is currently using PD7 (FSMC_NE1) for its chip select and PF0 (FSMC_A0) for its data/command signal. The SRAM is using PG9 (FSMC_NE2) for its chip select.
I've managed to get the SSD1963 up and running using the FSMC, but I am unable to get the FSMC working with the SRAM and this is where it gets confusing for me. The SSD1963 starts at 0x60000000, which sets up the FSMC to automatically set the CS (FSMC_NE1) when writing/reading to/from the SSD19 Since I want to use FSMC_NE2 for the CS of the SRAM, that needs to start at 0x64000000, or that is how I've understood it, but the SRAM only has 19 address lines. Which is probably causing my microcontroller to go into its default handler when I try to write to the SRAM. So my question is, how do I manage to get the FSMC to automatically set FSMC_NE2 without having to start at 0x64000000, or am I totally misunderstanding this concept? Here is my code that I'm using:
/* FSMC initialization function */
void MX_FSMC_Init(void)
{
FSMC_NORSRAM_TimingTypeDef Timing;
/** Perform the SRAM1 memory initialization sequence
*/
hsram1.Instance = FSMC_NORSRAM_DEVICE;
hsram1.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
/* hsram1.Init */
hsram1.Init.NSBank = FSMC_NORSRAM_BANK1;
hsram1.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
hsram1.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
hsram1.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram1.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
hsram1.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hsram1.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
hsram1.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
hsram1.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
hsram1.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
hsram1.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
hsram1.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram1.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
/* Timing */
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 255;
Timing.BusTurnAroundDuration = 15;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FSMC_ACCESS_MODE_A;
/* ExtTiming */
HAL_SRAM_Init(&hsram1, &Timing, NULL);
/** Perform the SRAM2 memory initialization sequence
*/
hsram2.Instance = FSMC_NORSRAM_DEVICE;
hsram2.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
/* hsram2.Init */
hsram2.Init.NSBank = FSMC_NORSRAM_BANK2;
hsram2.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
hsram2.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
hsram2.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
hsram2.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
hsram2.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
hsram2.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
hsram2.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
hsram2.Init.WriteOperation = FSMC_WRITE_OPERATION_DISABLE;
hsram2.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
hsram2.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;
hsram2.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
hsram2.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
/* Timing */
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 255;
Timing.BusTurnAroundDuration = 15;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FSMC_ACCESS_MODE_A;
/* ExtTiming */
HAL_SRAM_Init(&hsram2, &Timing, NULL);
}
static void HAL_FSMC_MspInit(void){
/* USER CODE BEGIN FSMC_MspInit 0 */
/* USER CODE END FSMC_MspInit 0 */
GPIO_InitTypeDef GPIO_InitStruct;
if (FSMC_Initialized) {
return;
}
FSMC_Initialized = 1;
/* Peripheral clock enable */
__FSMC_CLK_ENABLE();
/** FSMC GPIO Configuration
PF0 ------> FSMC_A0
PF1 ------> FSMC_A1
PF2 ------> FSMC_A2
PF3 ------> FSMC_A3
PF4 ------> FSMC_A4
PF5 ------> FSMC_A5
PF12 ------> FSMC_A6
PF13 ------> FSMC_A7
PF14 ------> FSMC_A8
PF15 ------> FSMC_A9
PG0 ------> FSMC_A10
PG1 ------> FSMC_A11
PE7 ------> FSMC_D4
PE8 ------> FSMC_D5
PE9 ------> FSMC_D6
PE10 ------> FSMC_D7
PE11 ------> FSMC_D8
PE12 ------> FSMC_D9
PE13 ------> FSMC_D10
PE14 ------> FSMC_D11
PE15 ------> FSMC_D12
PD8 ------> FSMC_D13
PD9 ------> FSMC_D14
PD10 ------> FSMC_D15
PD11 ------> FSMC_A16
PD12 ------> FSMC_A17
PD13 ------> FSMC_A18
PD14 ------> FSMC_D0
PD15 ------> FSMC_D1
PG2 ------> FSMC_A12
PG3 ------> FSMC_A13
PG4 ------> FSMC_A14
PG5 ------> FSMC_A15
PD0 ------> FSMC_D2
PD1 ------> FSMC_D3
PD4 ------> FSMC_NOE
PD5 ------> FSMC_NWE
PD7 ------> FSMC_NE1
PG9 ------> FSMC_NE2
PE0 ------> FSMC_NBL0
PE1 ------> FSMC_NBL1
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_12|GPIO_PIN_13
|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14
|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11
|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5
|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
GPIO_InitStruct.Alternate = GPIO_AF12_FSMC;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE BEGIN FSMC_MspInit 1 */
/* USER CODE END FSMC_MspInit 1 */
}
#define SRAM_BASE_ADDRESS ((uint32_t)0x64000000)
uint32_t *sram_ptr;
static void sram_write(uint32_t addr, uint16_t val){
sram_ptr = (uint32_t *)(SRAM_BASE_ADDRESS + addr);
*sram_ptr = val;
}
static uint16_t sram_read(uint32_t addr){
sram_ptr = (uint32_t *)(SRAM_BASE_ADDRESS + addr);
return *sram_ptr;
}
2015-08-17 03:57 PM
The micro-processor has a 32-bit address bus, the high order bits are decoded in the 0x60000000 region, and subdivides that into four banks. Yes, as far as I'm aware 0x64000000 will be NE4, the addressing on the SRAM will wrap at whatever range your wired address bits define.
What exactly are you calling the read/write functions that is causing it to fault? I'd probably localize the pointer.Can't help you with the HAL/Cube stuff, assuming CubeMX is generating the right code.2015-08-17 11:23 PM
> What exactly are you calling the read/write functions that is causing it to fault? I'd probably localize the pointer.
+1 Also, post the relevant FSMC registers' content. > 0x64000000 will be NE4 NE2, you meant. JW2015-08-18 12:27 AM
I've localized the pointer like you suggested. The crash occurs in the sram_write function after setting the pointer equal to val.
static void sram_write(uint32_t addr, uint16_t val){
uint32_t *sram_ptr;
sram_ptr = (uint32_t *)(SRAM_BASE_ADDRESS + addr);
*sram_ptr = val;
}
Here are the values for the FSMC registers:
BCR1 = 0x00001091
BTR1 = 0x0FFFFFFF
BCR2 = 0x00000091
BTR2 = 0x0FFFFFFF
In the BCR2 register it appears as if the write enable bit isn't being set.
2015-08-18 12:57 AM
> In the BCR2 register it appears as if the write enable bit isn't being set.
And what happens if you do set it? JW2015-08-18 01:28 AM
Probably the reason your SRAM has write disabled is this line:
hsram2.Init.WriteOperation = FSMC_WRITE_OPERATION_DISABLE;
That should cause an exception on write (but not read) requests, just as you see...
- Kristian.
2015-08-18 08:52 AM
Thanks. That fixed it!