From 578d7f5757613898d36fd999a409e5b9f5796136 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Sun, 22 May 2016 15:32:09 +0200 Subject: reindent/reformat to closer resemble rest of code base --- stm-fmc.c | 440 ++++++++++++++++++++++++++++---------------------------------- stm-fmc.h | 10 +- 2 files changed, 208 insertions(+), 242 deletions(-) diff --git a/stm-fmc.c b/stm-fmc.c index eca4b38..69dfb87 100644 --- a/stm-fmc.c +++ b/stm-fmc.c @@ -31,325 +31,283 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - - -//------------------------------------------------------------------------------ -// Headers -//------------------------------------------------------------------------------ -#include "stm-fmc.h" #include "stm32f4xx_hal.h" +#include "stm-fmc.h" -//------------------------------------------------------------------------------ -// Defined Values -//------------------------------------------------------------------------------ -#define FMC_FPGA_BASE_ADDR 0x60000000 -#define FMC_FPGA_ADDR_MASK 0x03FFFFFC // there are 26 physical lines, but "only" 24 usable for now -#define FMC_FPGA_NWAIT_MAX_POLL_TICKS 10 - -#define FMC_GPIO_PORT_NWAIT GPIOD -#define FMC_GPIO_PIN_NWAIT GPIO_PIN_6 - -#define FMC_NWAIT_IDLE GPIO_PIN_SET - - -//------------------------------------------------------------------------------ -// Variables -//------------------------------------------------------------------------------ static SRAM_HandleTypeDef _fmc_fpga_inst; - -//------------------------------------------------------------------------------ -// Prototypes -//------------------------------------------------------------------------------ static void _fmc_init_gpio(void); static void _fmc_init_params(void); static int _fmc_nwait_idle(void); -//------------------------------------------------------------------------------ void fmc_init(void) -//------------------------------------------------------------------------------ { - // configure fmc pins - _fmc_init_gpio(); + // configure fmc pins + _fmc_init_gpio(); - // configure fmc registers - _fmc_init_params(); + // configure fmc registers + _fmc_init_params(); } -//------------------------------------------------------------------------------ int fmc_write_32(uint32_t addr, uint32_t *data) -//------------------------------------------------------------------------------ { - // calculate target fpga address - uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); + // calculate target fpga address + uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); - // write data to fpga - HAL_StatusTypeDef ok = HAL_SRAM_Write_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // write data to fpga + HAL_StatusTypeDef ok = HAL_SRAM_Write_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for transaction to complete - int wait = _fmc_nwait_idle(); + // wait for transaction to complete + int wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // everything went ok - return 0; + // everything went ok + return 0; } -//------------------------------------------------------------------------------ int fmc_read_32(uint32_t addr, uint32_t *data) -//------------------------------------------------------------------------------ { - // calculate target fpga address - uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); + // calculate target fpga address + uint32_t ptr = FMC_FPGA_BASE_ADDR + (addr & FMC_FPGA_ADDR_MASK); - // perform dummy read transaction - HAL_StatusTypeDef ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // perform dummy read transaction + HAL_StatusTypeDef ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for dummy transaction to complete - int wait = _fmc_nwait_idle(); + // wait for dummy transaction to complete + int wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // read data from fpga - ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); + // read data from fpga + ok = HAL_SRAM_Read_32b(&_fmc_fpga_inst, (uint32_t *)ptr, data, 1); - // check for error - if (ok != HAL_OK) return -1; + // check for error + if (ok != HAL_OK) return -1; - // wait for read transaction to complete - wait = _fmc_nwait_idle(); + // wait for read transaction to complete + wait = _fmc_nwait_idle(); - // check for timeout - if (wait != 0) return -1; + // check for timeout + if (wait != 0) return -1; - // everything went ok - return 0; + // everything went ok + return 0; } -//------------------------------------------------------------------------------ static int _fmc_nwait_idle() -//------------------------------------------------------------------------------ { - int cnt; // counter + int cnt; // counter - // poll NWAIT (number of iterations is limited) - for (cnt=0; cnt= FMC_FPGA_NWAIT_MAX_POLL_TICKS) return -1; + // check for timeout + if (cnt >= FMC_FPGA_NWAIT_MAX_POLL_TICKS) return -1; - // ok - return 0; + // ok + return 0; } -//------------------------------------------------------------------------------ static void _fmc_init_gpio(void) -//------------------------------------------------------------------------------ { - // enable gpio clocks - __GPIOA_CLK_ENABLE(); - __GPIOB_CLK_ENABLE(); - __GPIOD_CLK_ENABLE(); - __GPIOE_CLK_ENABLE(); - __GPIOF_CLK_ENABLE(); - __GPIOG_CLK_ENABLE(); - __GPIOH_CLK_ENABLE(); - __GPIOI_CLK_ENABLE(); - - // enable fmc clock - __FMC_CLK_ENABLE(); - - // structure - GPIO_InitTypeDef GPIO_InitStruct; - - // Port B - GPIO_InitStruct.Pin = GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // Port D - 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_3|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_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - /* - * When FMC is working with fixed latency, NWAIT pin must not be - * configured in AF mode, according to STM32F429 errata. - */ - - // Port D (GPIO!) - GPIO_InitStruct.Pin = GPIO_PIN_6; - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; - GPIO_InitStruct.Pull = GPIO_PULLUP; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - // Port E - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|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_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - - // Port F - 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_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - - // Port G - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - - // Port H - 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_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - - // Port I - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + // enable gpio clocks + __GPIOA_CLK_ENABLE(); + __GPIOB_CLK_ENABLE(); + __GPIOD_CLK_ENABLE(); + __GPIOE_CLK_ENABLE(); + __GPIOF_CLK_ENABLE(); + __GPIOG_CLK_ENABLE(); + __GPIOH_CLK_ENABLE(); + __GPIOI_CLK_ENABLE(); + + // enable fmc clock + __FMC_CLK_ENABLE(); + + // structure + GPIO_InitTypeDef GPIO_InitStruct; + + // Port B + GPIO_InitStruct.Pin = GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + // Port D + 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_3|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_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* + * When FMC is working with fixed latency, NWAIT pin must not be + * configured in AF mode, according to STM32F429 errata. + */ + + // Port D (GPIO!) + GPIO_InitStruct.Pin = GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_PULLUP; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + // Port E + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|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_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + // Port F + 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_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + // Port G + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 + |GPIO_PIN_4|GPIO_PIN_5; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + // Port H + 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_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + + // Port I + GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 + |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); } -//------------------------------------------------------------------------------ static void _fmc_init_params(void) -//------------------------------------------------------------------------------ { - /* - * fill internal fields - */ - _fmc_fpga_inst.Instance = FMC_NORSRAM_DEVICE; - _fmc_fpga_inst.Extended = FMC_NORSRAM_EXTENDED_DEVICE; + /* + * fill internal fields + */ + _fmc_fpga_inst.Instance = FMC_NORSRAM_DEVICE; + _fmc_fpga_inst.Extended = FMC_NORSRAM_EXTENDED_DEVICE; - /* - * configure fmc interface settings - */ + /* + * configure fmc interface settings + */ - // use the first bank and corresponding chip select - _fmc_fpga_inst.Init.NSBank = FMC_NORSRAM_BANK1; + // use the first bank and corresponding chip select + _fmc_fpga_inst.Init.NSBank = FMC_NORSRAM_BANK1; - // data and address buses are separate - _fmc_fpga_inst.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; + // data and address buses are separate + _fmc_fpga_inst.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE; - // fpga mimics psram-type memory - _fmc_fpga_inst.Init.MemoryType = FMC_MEMORY_TYPE_PSRAM; + // fpga mimics psram-type memory + _fmc_fpga_inst.Init.MemoryType = FMC_MEMORY_TYPE_PSRAM; - // data bus is 32-bit - _fmc_fpga_inst.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32; + // data bus is 32-bit + _fmc_fpga_inst.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_32; - // read transaction is sync - _fmc_fpga_inst.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE; + // read transaction is sync + _fmc_fpga_inst.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_ENABLE; - // this _must_ be configured to high, according to errata, otherwise - // the processor may hang after trying to access fpga via fmc - _fmc_fpga_inst.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH; + // this _must_ be configured to high, according to errata, otherwise + // the processor may hang after trying to access fpga via fmc + _fmc_fpga_inst.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_HIGH; - // wrap mode is not supported - _fmc_fpga_inst.Init.WrapMode = FMC_WRAP_MODE_DISABLE; + // wrap mode is not supported + _fmc_fpga_inst.Init.WrapMode = FMC_WRAP_MODE_DISABLE; - // don't care in fixed latency mode - _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_DURING_WS; + // don't care in fixed latency mode + _fmc_fpga_inst.Init.WaitSignalActive = FMC_WAIT_TIMING_DURING_WS; - // allow write access to fpga - _fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; + // allow write access to fpga + _fmc_fpga_inst.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE; - // use fixed latency mode (ignore wait signal) - _fmc_fpga_inst.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; + // use fixed latency mode (ignore wait signal) + _fmc_fpga_inst.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE; - // write and read have same timing - _fmc_fpga_inst.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; + // write and read have same timing + _fmc_fpga_inst.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE; - // don't care in sync mode - _fmc_fpga_inst.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; + // don't care in sync mode + _fmc_fpga_inst.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE; - // write transaction is sync - _fmc_fpga_inst.Init.WriteBurst = FMC_WRITE_BURST_ENABLE; + // write transaction is sync + _fmc_fpga_inst.Init.WriteBurst = FMC_WRITE_BURST_ENABLE; - // keep clock always active - _fmc_fpga_inst.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC; + // keep clock always active + _fmc_fpga_inst.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ASYNC; - /* - * configure fmc timing parameters - */ - FMC_NORSRAM_TimingTypeDef fmc_timing; + /* + * configure fmc timing parameters + */ + FMC_NORSRAM_TimingTypeDef fmc_timing; - // don't care in sync mode - fmc_timing.AddressSetupTime = 15; + // don't care in sync mode + fmc_timing.AddressSetupTime = 15; - // don't care in sync mode - fmc_timing.AddressHoldTime = 15; + // don't care in sync mode + fmc_timing.AddressHoldTime = 15; - // don't care in sync mode - fmc_timing.DataSetupTime = 255; + // don't care in sync mode + fmc_timing.DataSetupTime = 255; - // not needed, since nwait will be polled manually - fmc_timing.BusTurnAroundDuration = 0; + // not needed, since nwait will be polled manually + fmc_timing.BusTurnAroundDuration = 0; - // use smallest allowed divisor for best performance - fmc_timing.CLKDivision = 2; + // use smallest allowed divisor for best performance + fmc_timing.CLKDivision = 2; - // stm is too slow to work with min allowed 2-cycle latency - fmc_timing.DataLatency = 3; + // stm is too slow to work with min allowed 2-cycle latency + fmc_timing.DataLatency = 3; - // don't care in sync mode - fmc_timing.AccessMode = FMC_ACCESS_MODE_A; + // don't care in sync mode + fmc_timing.AccessMode = FMC_ACCESS_MODE_A; - // initialize fmc - HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); + // initialize fmc + HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); } - - -//------------------------------------------------------------------------------ -// EOF -//------------------------------------------------------------------------------ diff --git a/stm-fmc.h b/stm-fmc.h index 9e34d32..7b73a94 100644 --- a/stm-fmc.h +++ b/stm-fmc.h @@ -35,7 +35,15 @@ #ifndef __STM_FMC_H #define __STM_FMC_H -#include +#define FMC_FPGA_BASE_ADDR 0x60000000 +#define FMC_FPGA_ADDR_MASK 0x03FFFFFC // there are 26 physical lines, but "only" 24 usable for now +#define FMC_FPGA_NWAIT_MAX_POLL_TICKS 10 + +#define FMC_GPIO_PORT_NWAIT GPIOD +#define FMC_GPIO_PIN_NWAIT GPIO_PIN_6 + +#define FMC_NWAIT_IDLE GPIO_PIN_SET + extern void fmc_init(void); -- cgit v1.2.3 From 50f9d40503e5f9cb24241c4c584db3cb94af07aa Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Mon, 23 May 2016 21:58:32 +0200 Subject: commit bugfix from Pavel fixing initialization of the second SDRAM chip --- .../TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c | 98 ++++++++++++++-------- 1 file changed, 61 insertions(+), 37 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c index bf28b4b..bdf38fc 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/stm32f4xx_ll_fmc.c @@ -1413,23 +1413,31 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe } else /* FMC_Bank2_SDRAM */ { - tmpr1 = Device->SDCR[FMC_SDRAM_BANK1]; - - /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ - tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ - FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ - FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); - - tmpr1 |= (uint32_t)(Init->SDClockPeriod |\ - Init->ReadBurst |\ - Init->ReadPipeDelay); - - tmpr2 = Device->SDCR[FMC_SDRAM_BANK2]; +/////////////////////////////// +// BEGIN PIECE OF WEIRD CODE // +/////////////////////////////// +// +// tmpr1 = Device->SDCR[FMC_SDRAM_BANK1]; +// +// /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ +// tmpr1 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ +// FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ +// FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); +// +// tmpr1 |= (uint32_t)(Init->SDClockPeriod |\ +// Init->ReadBurst |\ +// Init->ReadPipeDelay); +// +/////////////////////////////// +// END PIECE OF WEIRD CODE // +/////////////////////////////// + + tmpr2 = Device->SDCR[FMC_SDRAM_BANK1]; /* Clear NC, NR, MWID, NB, CAS, WP, SDCLK, RBURST, and RPIPE bits */ - tmpr2 &= ((uint32_t)~(FMC_SDCR1_NC | FMC_SDCR1_NR | FMC_SDCR1_MWID | \ - FMC_SDCR1_NB | FMC_SDCR1_CAS | FMC_SDCR1_WP | \ - FMC_SDCR1_SDCLK | FMC_SDCR1_RBURST | FMC_SDCR1_RPIPE)); + tmpr2 &= ((uint32_t)~(FMC_SDCR2_NC | FMC_SDCR2_NR | FMC_SDCR2_MWID | \ + FMC_SDCR2_NB | FMC_SDCR2_CAS | FMC_SDCR2_WP | \ + FMC_SDCR2_SDCLK | FMC_SDCR2_RBURST | FMC_SDCR2_RPIPE)); tmpr2 |= (uint32_t)(Init->ColumnBitsNumber |\ Init->RowBitsNumber |\ @@ -1438,7 +1446,9 @@ HAL_StatusTypeDef FMC_SDRAM_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_InitTypeDe Init->CASLatency |\ Init->WriteProtection); - Device->SDCR[FMC_SDRAM_BANK1] = tmpr1; +// +// Device->SDCR[FMC_SDRAM_BANK1] = tmpr1; +// Device->SDCR[FMC_SDRAM_BANK2] = tmpr2; } @@ -1490,30 +1500,44 @@ HAL_StatusTypeDef FMC_SDRAM_Timing_Init(FMC_SDRAM_TypeDef *Device, FMC_SDRAM_Tim } else /* FMC_Bank2_SDRAM */ { - tmpr1 = Device->SDTR[FMC_SDRAM_BANK2]; - - /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ - tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ - FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ - FMC_SDTR1_TRCD)); - - tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\ - (((Timing->ExitSelfRefreshDelay)-1) << 4) |\ - (((Timing->SelfRefreshTime)-1) << 8) |\ - (((Timing->WriteRecoveryTime)-1) <<16) |\ - (((Timing->RCDDelay)-1) << 24)); - +/////////////////////////////// +// BEGIN PIECE OF WEIRD CODE // +/////////////////////////////// +// +// tmpr1 = Device->SDTR[FMC_SDRAM_BANK2]; +// +// /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ +// tmpr1 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ +// FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ +// FMC_SDTR1_TRCD)); +// +// tmpr1 |= (uint32_t)(((Timing->LoadToActiveDelay)-1) |\ +// (((Timing->ExitSelfRefreshDelay)-1) << 4) |\ +// (((Timing->SelfRefreshTime)-1) << 8) |\ +// (((Timing->WriteRecoveryTime)-1) <<16) |\ +// (((Timing->RCDDelay)-1) << 24)); +// +/////////////////////////////// +// END PIECE OF WEIRD CODE // +/////////////////////////////// + tmpr2 = Device->SDTR[FMC_SDRAM_BANK1]; /* Clear TMRD, TXSR, TRAS, TRC, TWR, TRP and TRCD bits */ - tmpr2 &= ((uint32_t)~(FMC_SDTR1_TMRD | FMC_SDTR1_TXSR | FMC_SDTR1_TRAS | \ - FMC_SDTR1_TRC | FMC_SDTR1_TWR | FMC_SDTR1_TRP | \ - FMC_SDTR1_TRCD)); - tmpr2 |= (uint32_t)((((Timing->RowCycleDelay)-1) << 12) |\ - (((Timing->RPDelay)-1) << 20)); - - Device->SDTR[FMC_SDRAM_BANK2] = tmpr1; - Device->SDTR[FMC_SDRAM_BANK1] = tmpr2; + tmpr2 &= ((uint32_t)~(FMC_SDTR2_TMRD | FMC_SDTR2_TXSR | FMC_SDTR2_TRAS | \ + FMC_SDTR2_TRC | FMC_SDTR2_TWR | FMC_SDTR2_TRP | \ + FMC_SDTR2_TRCD)); + + tmpr2 |= (uint32_t)(((Timing->LoadToActiveDelay)-1U) |\ + (((Timing->ExitSelfRefreshDelay)-1U) << 4U) |\ + (((Timing->SelfRefreshTime)-1U) << 8U) |\ + (((Timing->WriteRecoveryTime)-1U) <<16U) |\ + (((Timing->RCDDelay)-1U) << 24U)); + +// +// Device->SDTR[FMC_SDRAM_BANK2] = tmpr1; +// + Device->SDTR[FMC_SDRAM_BANK2] = tmpr2; } return HAL_OK; -- cgit v1.2.3 From 6265025f7cd7f606b6da62c7add13a6008500cf7 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Mon, 23 May 2016 21:59:17 +0200 Subject: SDRAM initialization and test code from Pavel. Integrated into the cli-test program as such: cryptech> test sdram Initializing SDRAM Starting SDRAM test (n = 0) Run sequential write-then-read test for the first chip Run random write-then-read test for the first chip Run sequential write-then-read test for the second chip Run random write-then-read test for the second chip Run interleaved write-then-read test for both chips at once SDRAM test (n = 0) completed SDRAM test completed successfully cryptech> --- Makefile | 1 + .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h | 2 +- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c | 9 + projects/cli-test/Makefile | 2 +- projects/cli-test/cli-test.c | 98 +++++--- projects/cli-test/mgmt-cli.c | 4 - projects/cli-test/mgmt-cli.h | 33 ++- projects/cli-test/test_sdram.c | 274 +++++++++++++++++++++ projects/cli-test/test_sdram.h | 42 ++++ stm-fmc.c | 124 +++------- stm-fmc.h | 14 +- stm-init.c | 21 -- stm-init.h | 19 ++ stm-sdram.c | 267 ++++++++++++++++++++ stm-sdram.h | 66 +++++ 15 files changed, 828 insertions(+), 148 deletions(-) create mode 100644 projects/cli-test/test_sdram.c create mode 100644 projects/cli-test/test_sdram.h create mode 100644 stm-sdram.c create mode 100644 stm-sdram.h diff --git a/Makefile b/Makefile index 9c0661b..5166b08 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ export BOARD_OBJS = \ $(TOPLEVEL)/spiflash_n25q128.o \ $(TOPLEVEL)/stm-fpgacfg.o \ $(TOPLEVEL)/stm-keystore.o \ + $(TOPLEVEL)/stm-sdram.o \ $(TOPLEVEL)/syscalls.o \ $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \ $(BOARD_DIR)/system_stm32f4xx.o \ diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h index 3844481..8a11b8b 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h @@ -65,7 +65,7 @@ //#define HAL_NOR_MODULE_ENABLED //#define HAL_PCCARD_MODULE_ENABLED #define HAL_SRAM_MODULE_ENABLED -//#define HAL_SDRAM_MODULE_ENABLED +#define HAL_SDRAM_MODULE_ENABLED //#define HAL_HASH_MODULE_ENABLED #define HAL_GPIO_MODULE_ENABLED #define HAL_I2C_MODULE_ENABLED diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c index 6d1d029..2a207b6 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c @@ -107,6 +107,15 @@ void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef* hsram) { } +void HAL_SDRAM_MspInit(SDRAM_HandleTypeDef* hsdram) +{ +} + +void HAL_SDRAM_MspDeInit(SDRAM_HandleTypeDef* hsdram) +{ +} + + void HAL_UART_MspInit(UART_HandleTypeDef* huart) { GPIO_InitTypeDef GPIO_InitStruct; diff --git a/projects/cli-test/Makefile b/projects/cli-test/Makefile index f3976e4..7737e13 100644 --- a/projects/cli-test/Makefile +++ b/projects/cli-test/Makefile @@ -1,6 +1,6 @@ TEST = cli-test -OBJS = crc32.o mgmt-cli.o +OBJS = crc32.o mgmt-cli.o test_sdram.o CFLAGS += -I$(LIBCLI_DIR) LIBS += $(LIBCLI_DIR)/libcli.a diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c index 152c121..dfcf856 100644 --- a/projects/cli-test/cli-test.c +++ b/projects/cli-test/cli-test.c @@ -37,38 +37,12 @@ #include "stm-uart.h" #include "stm-fpgacfg.h" #include "stm-keystore.h" +#include "stm-sdram.h" #include "mgmt-cli.h" +#include "test_sdram.h" #include -/* A bunch of defines to make it easier to add/maintain the CLI commands. - * - */ -#define _cli_cmd_struct(name, fullname, func, help) \ - static struct cli_command cmd_##fullname##_s = \ - {(char *) #name, func, 0, help, \ - PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL} - -/* ROOT is a top-level label with no command */ -#define cli_command_root(name) \ - _cli_cmd_struct(name, name, NULL, NULL); \ - cli_register_command2(cli, &cmd_##name##_s, NULL) - -/* BRANCH is a label with a parent, but no command */ -#define cli_command_branch(parent, name) \ - _cli_cmd_struct(name, parent##_##name, NULL, NULL); \ - cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) - -/* NODE is a label with a parent and with a command associated with it */ -#define cli_command_node(parent, name, help) \ - _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \ - cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) - -/* ROOT NODE is a label without a parent, but with a command associated with it */ -#define cli_command_root_node(name, help) \ - _cli_cmd_struct(name, name, NULL, (char *) help); \ - cli_register_command2(cli, &cmd_##name##_s, NULL) - extern uint32_t update_crc(uint32_t crc, uint8_t *buf, int len); @@ -306,6 +280,64 @@ int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc) while (1) {}; } +int cmd_test_sdram(struct cli_def *cli, const char *command, char *argv[], int argc) +{ + // run external memory initialization sequence + HAL_StatusTypeDef status; + int ok, n = 1, test_completed; + + cli_print(cli, "Initializing SDRAM"); + status = sdram_init(); + if (status != HAL_OK) { + cli_print(cli, "Failed initializing SDRAM: %i", (int) status); + return CLI_OK; + } + + /* XXX support number of iterations given as argument like 'test sdram 5' */ + while (n--) { + cli_print(cli, "Starting SDRAM test (n = %i)", n); + test_completed = 0; + // set LFSRs to some initial value, LFSRs will produce + // pseudo-random 32-bit patterns to test our memories + lfsr1 = 0xCCAA5533; + lfsr2 = 0xCCAA5533; + + cli_print(cli, "Run sequential write-then-read test for the first chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the first chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP1); + if (!ok) break; + + cli_print(cli, "Run sequential write-then-read test for the second chip"); + ok = test_sdram_sequential(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + cli_print(cli, "Run random write-then-read test for the second chip"); + ok = test_sdram_random(SDRAM_BASEADDR_CHIP2); + if (!ok) break; + + // turn blue led on (testing two chips at the same time) + led_on(LED_BLUE); + + cli_print(cli, "Run interleaved write-then-read test for both chips at once"); + ok = test_sdrams_interleaved(SDRAM_BASEADDR_CHIP1, SDRAM_BASEADDR_CHIP2); + + led_off(LED_BLUE); + test_completed = 1; + cli_print(cli, "SDRAM test (n = %i) completed", n); + } + + if (! test_completed) { + cli_print(cli, "SDRAM test failed (n = %i)", n); + } else { + cli_print(cli, "SDRAM test completed successfully"); + } + + return CLI_OK; +} + int check_auth(const char *username, const char *password) { if (strcasecmp(username, "ct") != 0) @@ -349,6 +381,15 @@ void configure_cli_fpga(struct cli_def *cli) cli_command_node(fpga_bitstream, erase, "Erase FPGA config memory"); } +void configure_cli_test(struct cli_def *cli) +{ + /* test */ + cli_command_root(test); + + /* test sdram */ + cli_command_node(test, sdram, "Run SDRAM tests"); +} + void configure_cli_misc(struct cli_def *cli) { /* filetransfer */ @@ -371,6 +412,7 @@ main() configure_cli_show(&cli); configure_cli_fpga(&cli); + configure_cli_test(&cli); configure_cli_misc(&cli); led_off(LED_RED); diff --git a/projects/cli-test/mgmt-cli.c b/projects/cli-test/mgmt-cli.c index 8d53515..faaafda 100644 --- a/projects/cli-test/mgmt-cli.c +++ b/projects/cli-test/mgmt-cli.c @@ -33,7 +33,6 @@ */ #include "stm32f4xx_hal.h" #include "stm-init.h" -#include "stm-led.h" #include "stm-uart.h" #include "mgmt-cli.h" @@ -79,11 +78,8 @@ int embedded_cli_loop(struct cli_def *cli) while (1) { cli_loop_start_new_command(cli, &ctx); - HAL_GPIO_TogglePin(LED_PORT, LED_YELLOW); while (1) { - HAL_GPIO_TogglePin(LED_PORT, LED_BLUE); - cli_loop_show_prompt(cli, &ctx); n = cli_loop_read_next_char(cli, &ctx, &c); diff --git a/projects/cli-test/mgmt-cli.h b/projects/cli-test/mgmt-cli.h index 2f1f139..e6780a3 100644 --- a/projects/cli-test/mgmt-cli.h +++ b/projects/cli-test/mgmt-cli.h @@ -38,13 +38,40 @@ #include "stm32f4xx_hal.h" #include + +/* A bunch of defines to make it easier to add/maintain the CLI commands. + * + */ +#define _cli_cmd_struct(name, fullname, func, help) \ + static struct cli_command cmd_##fullname##_s = \ + {(char *) #name, func, 0, help, \ + PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL} + +/* ROOT is a top-level label with no command */ +#define cli_command_root(name) \ + _cli_cmd_struct(name, name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + +/* BRANCH is a label with a parent, but no command */ +#define cli_command_branch(parent, name) \ + _cli_cmd_struct(name, parent##_##name, NULL, NULL); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* NODE is a label with a parent and with a command associated with it */ +#define cli_command_node(parent, name, help) \ + _cli_cmd_struct(name, parent##_##name, cmd_##parent##_##name, (char *) help); \ + cli_register_command2(cli, &cmd_##parent##_##name##_s, &cmd_##parent##_s) + +/* ROOT NODE is a label without a parent, but with a command associated with it */ +#define cli_command_root_node(name, help) \ + _cli_cmd_struct(name, name, NULL, (char *) help); \ + cli_register_command2(cli, &cmd_##name##_s, NULL) + + extern void uart_cli_print(struct cli_def *cli __attribute__ ((unused)), const char *buf); extern int uart_cli_read(struct cli_def *cli __attribute__ ((unused)), void *buf, size_t count); extern int uart_cli_write(struct cli_def *cli __attribute__ ((unused)), const void *buf, size_t count); extern int embedded_cli_loop(struct cli_def *cli); extern void mgmt_cli_init(struct cli_def *cli); -extern __IO ITStatus MgmtUartDataReceived; -extern __IO ITStatus MgmtUartShouldCli; - #endif /* __STM32_MGMT_CLI_H */ diff --git a/projects/cli-test/test_sdram.c b/projects/cli-test/test_sdram.c new file mode 100644 index 0000000..e720667 --- /dev/null +++ b/projects/cli-test/test_sdram.c @@ -0,0 +1,274 @@ +/* + * test_sdram.c + * ------------ + * Test code for the 2x512 MBit SDRAM working memory. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "stm32f4xx_hal.h" +#include "stm-led.h" +#include "stm-sdram.h" +#include "test_sdram.h" + + +uint32_t lfsr1; +uint32_t lfsr2; + + +int test_sdram_sequential(uint32_t *base_addr) +{ + // memory offset + int offset; + + // readback value + uint32_t sdram_readback; + + + /* This test fills entire memory chip with some pseudo-random pattern + starting from the very first cell and going in linear fashion. It then + reads entire memory and compares read values with what was written. */ + + + // turn on yellow led to indicate, that we're writing + led_on(LED_YELLOW); + + + // + // Note, that SDRAM_SIZE is in BYTES, and since we write using + // 32-bit words, total number of words is SDRAM_SIZE / 4. + // + + // fill entire memory with "random" values + for (offset=0; offset<(SDRAM_SIZE >> 2); offset++) { + // generate next "random" value to write + lfsr1 = lfsr_next_32(lfsr1); + + // write to memory + base_addr[offset] = lfsr1; + } + + + // turn off yellow led to indicate, that we're going to read + led_off(LED_YELLOW); + + + // read entire memory and compare values + for (offset=0; offset<(SDRAM_SIZE >> 2); offset++) { + // generate next "random" value (we use the second LFSR to catch up) + lfsr2 = lfsr_next_32(lfsr2); + + // read from memory + sdram_readback = base_addr[offset]; + + // compare and abort test in case of mismatch + if (sdram_readback != lfsr2) return 0; + } + + // done + return 1; +} + + +//----------------------------------------------------------------------------- +int test_sdram_random(uint32_t *base_addr) +//----------------------------------------------------------------------------- +{ + // cell counter, memory offset + int counter, offset; + + // readback value + uint32_t sdram_readback; + + + /* This test fills entire memory chip with some pseudo-random pattern + starting from the very first cell, but then jumping around in pseudo- + random fashion to make sure, that SDRAM controller in STM32 handles + bank, row and column switching correctly. It then reads entire memory + and compares read values with what was written. */ + + + // turn on yellow led to indicate, that we're writing + led_on(LED_YELLOW); + + + // + // Note, that SDRAM_SIZE is in BYTES, and since we write using + // 32-bit words, total number of words is SDRAM_SIZE / 4. + // + + // start with the first cell + for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++) { + // generate next "random" value to write + lfsr1 = lfsr_next_32(lfsr1); + + // write to memory + base_addr[offset] = lfsr1; + + // generate next "random" address + + // + // Note, that for 64 MB memory with 32-bit data bus we need 24 bits + // of address, so we use 24-bit LFSR here. Since LFSR has only 2^^24-1 + // states, i.e. all possible 24-bit values excluding 0, we have to + // manually kick it into some arbitrary state during the first iteration. + // + + offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE; + } + + + // turn off yellow led to indicate, that we're going to read + led_off(LED_YELLOW); + + + // read entire memory and compare values + for (counter=0, offset=0; counter<(SDRAM_SIZE >> 2); counter++) { + // generate next "random" value (we use the second LFSR to catch up) + lfsr2 = lfsr_next_32(lfsr2); + + // read from memory + sdram_readback = base_addr[offset]; + + // compare and abort test in case of mismatch + if (sdram_readback != lfsr2) return 0; + + // generate next "random" address + offset = offset ? lfsr_next_24(offset) : 0x00DEC0DE; + } + + // + // we should have walked exactly 2**24 iterations and returned + // back to the arbitrary starting address... + // + + if (offset != 0x00DEC0DE) return 0; + + + // done + return 1; +} + + +//----------------------------------------------------------------------------- +int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2) +//----------------------------------------------------------------------------- +{ + // cell counter, memory offsets + int counter, offset1, offset2; + + // readback value + uint32_t sdram_readback; + + + /* Basically this is the same as test_sdram_random() except that it + tests both memory chips at the same time. */ + + + // turn on yellow led to indicate, that we're writing + led_on(LED_YELLOW); + + + // + // Note, that SDRAM_SIZE is in BYTES, and since we write using + // 32-bit words, total number of words is SDRAM_SIZE / 4. + // + + // start with the first cell + for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++) { + // generate next "random" value to write + lfsr1 = lfsr_next_32(lfsr1); + + // write to memory + base_addr1[offset1] = lfsr1; + base_addr2[offset2] = lfsr1; + + // generate next "random" addresses (use different starting states!) + + offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF; + offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA; + } + + + // turn off yellow led to indicate, that we're going to read + led_off(LED_YELLOW); + + + // read entire memory and compare values + for (counter=0, offset1=0, offset2=0; counter<(SDRAM_SIZE >> 2); counter++) { + // generate next "random" value (we use the second LFSR to catch up) + lfsr2 = lfsr_next_32(lfsr2); + + // read from the first memory and compare + sdram_readback = base_addr1[offset1]; + if (sdram_readback != lfsr2) return 0; + + // read from the second memory and compare + sdram_readback = base_addr2[offset2]; + if (sdram_readback != lfsr2) return 0; + + // generate next "random" addresses + offset1 = offset1 ? lfsr_next_24(offset1) : 0x00ABCDEF; + offset2 = offset2 ? lfsr_next_24(offset2) : 0x00FEDCBA; + } + + // + // we should have walked exactly 2**24 iterations and returned + // back to the arbitrary starting address... + // + + if (offset1 != 0x00ABCDEF) return 0; + if (offset2 != 0x00FEDCBA) return 0; + + // done + return 1; +} + +uint32_t lfsr_next_32(uint32_t lfsr) +{ + uint32_t tap = 0; + + tap ^= (lfsr >> 31); + tap ^= (lfsr >> 30); + tap ^= (lfsr >> 29); + tap ^= (lfsr >> 9); + + return (lfsr << 1) | (tap & 1); +} + +uint32_t lfsr_next_24(uint32_t lfsr) +{ + unsigned int tap = 0; + + tap ^= (lfsr >> 23); + tap ^= (lfsr >> 22); + tap ^= (lfsr >> 21); + tap ^= (lfsr >> 16); + + return ((lfsr << 1) | (tap & 1)) & 0x00FFFFFF; +} diff --git a/projects/cli-test/test_sdram.h b/projects/cli-test/test_sdram.h new file mode 100644 index 0000000..b848d18 --- /dev/null +++ b/projects/cli-test/test_sdram.h @@ -0,0 +1,42 @@ +/* + * test_sdram.h + * ------------ + * Prototypes and defines for testing the 2x512 MBit SDRAM working memory. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +extern uint32_t lfsr1; +extern uint32_t lfsr2; + +extern int test_sdram_sequential(uint32_t *base_addr); +extern int test_sdram_random(uint32_t *base_addr); +extern int test_sdrams_interleaved(uint32_t *base_addr1, uint32_t *base_addr2); + +extern uint32_t lfsr_next_32(uint32_t lfsr); +extern uint32_t lfsr_next_24(uint32_t lfsr); diff --git a/stm-fmc.c b/stm-fmc.c index 69dfb87..698f7af 100644 --- a/stm-fmc.c +++ b/stm-fmc.c @@ -32,23 +32,30 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stm32f4xx_hal.h" +#include "stm-init.h" #include "stm-fmc.h" static SRAM_HandleTypeDef _fmc_fpga_inst; -static void _fmc_init_gpio(void); -static void _fmc_init_params(void); +static HAL_StatusTypeDef _fmc_init_params(void); static int _fmc_nwait_idle(void); -void fmc_init(void) +HAL_StatusTypeDef fmc_init(void) { + static int initialized = 0; + + if (initialized) { + return HAL_OK; + } + initialized = 1; + // configure fmc pins - _fmc_init_gpio(); + fmc_init_gpio(); // configure fmc registers - _fmc_init_params(); + return _fmc_init_params(); } @@ -129,104 +136,45 @@ static int _fmc_nwait_idle() return 0; } -static void _fmc_init_gpio(void) +void fmc_init_gpio(void) { - // enable gpio clocks - __GPIOA_CLK_ENABLE(); - __GPIOB_CLK_ENABLE(); - __GPIOD_CLK_ENABLE(); - __GPIOE_CLK_ENABLE(); - __GPIOF_CLK_ENABLE(); - __GPIOG_CLK_ENABLE(); - __GPIOH_CLK_ENABLE(); - __GPIOI_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct; // enable fmc clock - __FMC_CLK_ENABLE(); + __HAL_RCC_FMC_CLK_ENABLE(); - // structure - GPIO_InitTypeDef GPIO_InitStruct; - - // Port B - GPIO_InitStruct.Pin = GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); - - // Port D - 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_3|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_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + fmc_af_gpio(GPIOB, GPIO_PIN_7); + fmc_af_gpio(GPIOD, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_3 | GPIO_PIN_4 + | GPIO_PIN_5 | 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); /* - * When FMC is working with fixed latency, NWAIT pin must not be + * When FMC is working with fixed latency, NWAIT pin (PD6) must not be * configured in AF mode, according to STM32F429 errata. */ - - // Port D (GPIO!) GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - // Port E - GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|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_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); - - // Port F - 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_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); - - // Port G - GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 - |GPIO_PIN_4|GPIO_PIN_5; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); - - // Port H - 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_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); - - // Port I - GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_0|GPIO_PIN_1 - |GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_6|GPIO_PIN_7; - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; - GPIO_InitStruct.Alternate = GPIO_AF12_FMC; - HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); + fmc_af_gpio(GPIOE, GPIO_PIN_2 + | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | 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); + fmc_af_gpio(GPIOF, 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); + fmc_af_gpio(GPIOG, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 + | GPIO_PIN_4 | GPIO_PIN_5); + fmc_af_gpio(GPIOH, GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 + | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + fmc_af_gpio(GPIOI, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 + | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10); } -static void _fmc_init_params(void) +static HAL_StatusTypeDef _fmc_init_params(void) { /* * fill internal fields @@ -309,5 +257,5 @@ static void _fmc_init_params(void) fmc_timing.AccessMode = FMC_ACCESS_MODE_A; // initialize fmc - HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); + return HAL_SRAM_Init(&_fmc_fpga_inst, &fmc_timing, NULL); } diff --git a/stm-fmc.h b/stm-fmc.h index 7b73a94..1e6a670 100644 --- a/stm-fmc.h +++ b/stm-fmc.h @@ -44,8 +44,18 @@ #define FMC_NWAIT_IDLE GPIO_PIN_SET - -extern void fmc_init(void); +#define fmc_af_gpio(port, pins) \ + GPIO_InitStruct.Pin = pins; \ + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; \ + GPIO_InitStruct.Pull = GPIO_NOPULL; \ + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; \ + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; \ + __HAL_RCC_##port##_CLK_ENABLE(); \ + HAL_GPIO_Init(port, &GPIO_InitStruct) + + +extern HAL_StatusTypeDef fmc_init(void); +extern void fmc_init_gpio(void); extern int fmc_write_32(uint32_t addr, uint32_t *data); extern int fmc_read_32(uint32_t addr, uint32_t *data); diff --git a/stm-init.c b/stm-init.c index 7ded2a6..c8228d8 100644 --- a/stm-init.c +++ b/stm-init.c @@ -38,9 +38,6 @@ #ifdef HAL_GPIO_MODULE_ENABLED #include "stm-led.h" #endif -#ifdef HAL_SRAM_MODULE_ENABLED -#include "stm-fmc.h" -#endif #ifdef HAL_UART_MODULE_ENABLED #include "stm-uart.h" #endif @@ -143,24 +140,6 @@ static void MX_USART2_UART_Init(void) #ifdef HAL_GPIO_MODULE_ENABLED -#define gpio_output(output_port, output_pins, output_level) \ - /* Configure GPIO pin Output Level */ \ - HAL_GPIO_WritePin(output_port, output_pins, output_level); \ - /* Configure pin as output */ \ - GPIO_InitStruct.Pin = output_pins; \ - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \ - GPIO_InitStruct.Pull = GPIO_NOPULL; \ - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ - HAL_GPIO_Init(output_port, &GPIO_InitStruct) - -#define gpio_input(input_port, input_pin, input_pull) \ - GPIO_InitStruct.Pin = input_pin; \ - GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \ - GPIO_InitStruct.Pull = input_pull; \ - GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ - HAL_GPIO_Init(input_port, &GPIO_InitStruct) - - /* Configure General Purpose Input/Output pins */ static void MX_GPIO_Init(void) { diff --git a/stm-init.h b/stm-init.h index ed80d01..dd19311 100644 --- a/stm-init.h +++ b/stm-init.h @@ -38,6 +38,25 @@ #include "cmsis_os.h" #include "stm32f4xx_hal.h" +/* Macros used to make GPIO pin setup (in stm-init.c) easier */ +#define gpio_output(output_port, output_pins, output_level) \ + /* Configure GPIO pin Output Level */ \ + HAL_GPIO_WritePin(output_port, output_pins, output_level); \ + /* Configure pin as output */ \ + GPIO_InitStruct.Pin = output_pins; \ + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \ + GPIO_InitStruct.Pull = GPIO_NOPULL; \ + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ + HAL_GPIO_Init(output_port, &GPIO_InitStruct) + +#define gpio_input(input_port, input_pin, input_pull) \ + GPIO_InitStruct.Pin = input_pin; \ + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \ + GPIO_InitStruct.Pull = input_pull; \ + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \ + HAL_GPIO_Init(input_port, &GPIO_InitStruct) + + extern void stm_init(void); extern void Error_Handler(void); diff --git a/stm-sdram.c b/stm-sdram.c new file mode 100644 index 0000000..0ec8065 --- /dev/null +++ b/stm-sdram.c @@ -0,0 +1,267 @@ +/* + * stm-sdram.c + * ----------- + * Functions concerning the 2x512 Mbit SDRAM working memory. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "stm32f4xx_hal.h" +#include "stm-init.h" +#include "stm-sdram.h" +#include "stm-fmc.h" +#include "stm-led.h" + +SDRAM_HandleTypeDef hsdram1; +SDRAM_HandleTypeDef hsdram2; + +void _sdram_init_gpio(void); +HAL_StatusTypeDef _sdram_init_fmc(void); +HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2); + + +HAL_StatusTypeDef sdram_init(void) +{ + HAL_StatusTypeDef status; + static int initialized = 0; + + if (initialized) { + return; + } + initialized = 1; + + /* We rely on several things being set up by fmc_init() instead of duplicating all + * that code here for independent FPGA/SDRAM FMC setup. This means the FPGA<->STM32 + * FMC bus can be used without the SDRAMs initialized, but the SDRAMs can't be + * initialized withouth the FPGA<->STM32 FMC bus being set up too. + */ + fmc_init(); + + // configure FMC + _sdram_init_gpio(); + status = _sdram_init_fmc(); + if (status != HAL_OK) return status; + + // configure SDRAM registers + status = _sdram_init_params(&hsdram1, &hsdram2); + if (status != HAL_OK) return status; + + return HAL_OK; +} + +void _sdram_init_gpio(void) +{ + GPIO_InitTypeDef GPIO_InitStruct; + + /* The bulk of the FMC GPIO pins are set up in fmc_init_gpio(). + * This function just needs to enable the additional ones used + * with the SDRAMs. + */ + fmc_af_gpio(GPIOB, GPIO_PIN_5 | GPIO_PIN_6); + fmc_af_gpio(GPIOC, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3); + fmc_af_gpio(GPIOE, GPIO_PIN_0 | GPIO_PIN_1); + fmc_af_gpio(GPIOF, GPIO_PIN_11); + fmc_af_gpio(GPIOG, GPIO_PIN_8 | GPIO_PIN_15); + fmc_af_gpio(GPIOI, GPIO_PIN_4 | GPIO_PIN_5); +} + +HAL_StatusTypeDef _sdram_init_fmc() +{ + HAL_StatusTypeDef status; + FMC_SDRAM_TimingTypeDef SdramTiming; + + /* + * following settings are for -75E speed grade memory chip + * clocked at only 90 MHz instead of the rated 133 MHz + * + * ExitSelfRefreshDelay: 67 ns @ 90 MHz is 6.03 cycles, so in theory + * 6 can be used here, but let's be on the safe side + * + * WriteRecoveryTime: must be >= tRAS - tRCD (5 - 2 = 3 cycles), + * and >= tRC - tRCD - tRP (8 - 2 - 2 = 4 cycles) + */ + SdramTiming.LoadToActiveDelay = 2; // tMRD + SdramTiming.ExitSelfRefreshDelay = 7; // (see above) + SdramTiming.SelfRefreshTime = 5; // should be >= tRAS (5 cycles) + SdramTiming.RowCycleDelay = 8; // tRC + SdramTiming.WriteRecoveryTime = 4; // (see above) + SdramTiming.RPDelay = 2; // tRP + SdramTiming.RCDDelay = 2; // tRCD + + /* + * configure the first bank + */ + + // memory type + hsdram1.Instance = FMC_SDRAM_DEVICE; + + // bank + hsdram1.Init.SDBank = FMC_SDRAM_BANK1; + + // settings for IS42S32160F + hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9; + hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13; + hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32; + hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; + hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2; + + // write protection not needed + hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; + + // memory clock is 90 MHz (HCLK / 2) + hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; + + // read burst not needed + hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE; + + // additional pipeline stages not neeed + hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0; + + // call HAL layer + status = HAL_SDRAM_Init(&hsdram1, &SdramTiming); + if (status != HAL_OK) return status; + + /* + * configure the second bank + */ + + // memory type + hsdram2.Instance = FMC_SDRAM_DEVICE; + + // bank number + hsdram2.Init.SDBank = FMC_SDRAM_BANK2; + + // settings for IS42S32160F + hsdram2.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9; + hsdram2.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13; + hsdram2.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32; + hsdram2.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; + hsdram2.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2; + + // write protection not needed + hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; + + // memory clock is 90 MHz (HCLK / 2) + hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; + + // read burst not needed + hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE; + + // additional pipeline stages not neeed + hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0; + + // call HAL layer + return HAL_SDRAM_Init(&hsdram2, &SdramTiming); +} + +HAL_StatusTypeDef _sdram_init_params(SDRAM_HandleTypeDef *sdram1, SDRAM_HandleTypeDef *sdram2) +{ + HAL_StatusTypeDef ok; // status + FMC_SDRAM_CommandTypeDef cmd; // command + + /* + * enable clocking + */ + cmd.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; + cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2; + cmd.AutoRefreshNumber = 1; + cmd.ModeRegisterDefinition = 0; + + HAL_Delay(1); + ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1); + if (ok != HAL_OK) return ok; + + /* + * precharge all banks + */ + cmd.CommandMode = FMC_SDRAM_CMD_PALL; + cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2; + cmd.AutoRefreshNumber = 1; + cmd.ModeRegisterDefinition = 0; + + HAL_Delay(1); + ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1); + if (ok != HAL_OK) return ok; + + + /* + * send two auto-refresh commands in a row + */ + cmd.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; + cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2; + cmd.AutoRefreshNumber = 1; + cmd.ModeRegisterDefinition = 0; + + ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1); + if (ok != HAL_OK) return ok; + + ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1); + if (ok != HAL_OK) return ok; + + + /* + * load mode register + */ + cmd.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; + cmd.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2; + cmd.AutoRefreshNumber = 1; + cmd.ModeRegisterDefinition = + SDRAM_MODEREG_BURST_LENGTH_1 | + SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | + SDRAM_MODEREG_CAS_LATENCY_2 | + SDRAM_MODEREG_OPERATING_MODE_STANDARD | + SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ; + + ok = HAL_SDRAM_SendCommand(sdram1, &cmd, 1); + if (ok != HAL_OK) return ok; + + + /* + * set number of consequtive auto-refresh commands + * and program refresh rate + * + * RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc + * + * RefreshCycles = 7.8125 us * 90 MHz = 703 + * + * According to the formula on p.1665 of the reference manual, + * we also need to subtract 20 from the value, so the target + * refresh rate is 703 - 20 = 683. + */ + + ok = HAL_SDRAM_SetAutoRefreshNumber(sdram1, 8); + if (ok != HAL_OK) return ok; + + HAL_SDRAM_ProgramRefreshRate(sdram1, 683); + if (ok != HAL_OK) return ok; + + /* + * done + */ + return HAL_OK; +} diff --git a/stm-sdram.h b/stm-sdram.h new file mode 100644 index 0000000..8f58b34 --- /dev/null +++ b/stm-sdram.h @@ -0,0 +1,66 @@ +/* + * stm-sdram.h + * ----------- + * Functions and defines concerning the 2x512 Mbit SDRAM working memory. + * + * Copyright (c) 2016, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __STM32_SDRAM_H +#define __STM32_SDRAM_H + +/* Base Addresses */ +#define SDRAM_BASEADDR_CHIP1 ((uint32_t *)0xC0000000) +#define SDRAM_BASEADDR_CHIP2 ((uint32_t *)0xD0000000) + +/* Memory Size, 64 MBytes (512 Mbits) */ +#define SDRAM_SIZE 0x4000000 + +/* Mode Register Bits */ +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) + +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) + +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) + +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) + +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +extern SDRAM_HandleTypeDef hsdram1; +extern SDRAM_HandleTypeDef hsdram2; + +extern HAL_StatusTypeDef sdram_init(void); + +#endif -- cgit v1.2.3