diff options
-rw-r--r-- | stm-fmc.c | 440 | ||||
-rw-r--r-- | stm-fmc.h | 10 |
2 files changed, 208 insertions, 242 deletions
@@ -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; cnt++) - { - // read pin state - GPIO_PinState nwait = HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT); + // poll NWAIT (number of iterations is limited) + for (cnt=0; cnt<FMC_FPGA_NWAIT_MAX_POLL_TICKS; cnt++) + { + // read pin state + GPIO_PinState nwait = HAL_GPIO_ReadPin(FMC_GPIO_PORT_NWAIT, FMC_GPIO_PIN_NWAIT); - // stop waiting if fpga is ready - if (nwait == FMC_NWAIT_IDLE) break; - } + // stop waiting if fpga is ready + if (nwait == FMC_NWAIT_IDLE) break; + } - // check for timeout - if (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 -//------------------------------------------------------------------------------ @@ -35,7 +35,15 @@ #ifndef __STM_FMC_H #define __STM_FMC_H -#include <stdint.h> +#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); |