Browse Source

Updates for STM32F429 chip

After a few rounds of review, changes are added to support
additional peripherals of the STM32F427/429
pull/259/merge
cmcmanis 11 years ago
committed by Frantisek Burian
parent
commit
07d0076934
  1. 3
      include/libopencm3/stm32/common/spi_common_all.h
  2. 16
      include/libopencm3/stm32/common/usart_common_f24.h
  3. 247
      include/libopencm3/stm32/f4/fmc.h
  4. 14
      include/libopencm3/stm32/f4/irq.json
  5. 34
      include/libopencm3/stm32/f4/memorymap.h
  6. 7
      include/libopencm3/stm32/f4/rcc.h
  7. 4
      include/libopencm3/stm32/fsmc.h
  8. 2
      lib/stm32/f4/Makefile
  9. 99
      lib/stm32/f4/fmc.c

3
include/libopencm3/stm32/common/spi_common_all.h

@ -48,6 +48,9 @@ specific memorymap.h header before including this header file.*/
#define SPI1 SPI1_BASE
#define SPI2 SPI2_I2S_BASE
#define SPI3 SPI3_I2S_BASE
#define SPI4 SPI4_BASE
#define SPI5 SPI5_BASE
#define SPI6 SPI6_BASE
/**@}*/
/* --- SPI registers ------------------------------------------------------- */

16
include/libopencm3/stm32/common/usart_common_f24.h

@ -39,29 +39,45 @@ specific memorymap.h header before including this header file.*/
/* --- Convenience macros -------------------------------------------------- */
#define USART6 USART6_BASE
#define UART7 UART7_BASE
#define UART8 UART8_BASE
/* --- USART registers ----------------------------------------------------- */
/* Status register (USARTx_SR) */
#define USART6_SR USART_SR(USART6_BASE)
#define UART7_SR USART_SR(UART7)
#define UART8_SR USART_SR(UART8)
/* Data register (USARTx_DR) */
#define USART6_DR USART_DR(USART6_BASE)
#define UART7_DR USART_DR(UART7)
#define UART8_DR USART_DR(UART8)
/* Baud rate register (USARTx_BRR) */
#define USART6_BRR USART_BRR(USART6_BASE)
#define UART7_BRR USART_BRR(UART7)
#define UART8_BRR USART_BRR(UART8)
/* Control register 1 (USARTx_CR1) */
#define USART6_CR1 USART_CR1(USART6_BASE)
#define UART7_CR1 USART_CR1(UART7)
#define UART8_CR1 USART_CR1(UART8)
/* Control register 2 (USARTx_CR2) */
#define USART6_CR2 USART_CR2(USART6_BASE)
#define UART7_CR2 USART_CR2(UART7)
#define UART8_CR2 USART_CR2(UART8)
/* Control register 3 (USARTx_CR3) */
#define USART6_CR3 USART_CR3(USART6_BASE)
#define UART7_CR3 USART_CR3(UART7)
#define UART8_CR3 USART_CR3(UART8)
/* Guard time and prescaler register (USARTx_GTPR) */
#define USART6_GTPR USART_GTPR(USART6_BASE)
#define UART7_GTPR USART_GTPR(UART7)
#define UART8_GTPR USART_GTPR(UART8)
/* --- USART_CR1 values ---------------------------------------------------- */

247
include/libopencm3/stm32/f4/fmc.h

@ -0,0 +1,247 @@
/* vim: set noexpandtab ts=8 :
* This file is part of the libopencm3 project.
*
* Copyright (C) 2013 Chuck McManis <cmcmanis@mcmanis.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_FMC_H
#define LIBOPENCM3_FMC_H
#ifndef LIBOPENCM3_FSMC_H
error "This file should not be included directly, it is included with fsmc.h"
#endif
/* --- Convenience macros -------------------------------------------------- */
#define FMC_BANK5_BASE 0xa0000000U
#define FMC_BANK6_BASE 0xb0000000U
#define FMC_BANK7_BASE 0xc0000000U
#define FMC_BANK8_BASE 0xd0000000U
/* --- FMC registers ------------------------------------------------------ */
/* SDRAM Control Registers 1 .. 2 */
#define FMC_SDCR(x) MMIO32(FSMC_BASE + 0x140 + 4 * x)
#define FMC_SDCR1 FMC_SDCR(0)
#define FMC_SDCR2 FMC_SDCR(1)
/* SDRAM Timing Registers 1 .. 2 */
#define FMC_SDTR(x) MMIO32(FSMC_BASE + 0x148 + 4 * x)
#define FMC_SDTR1 FMC_SDTR(0)
#define FMC_SDTR2 FMC_SDTR(1)
/* SDRAM Command Mode Register */
#define FMC_SDCMR MMIO32(FSMC_BASE + (uint32_t) 0x150)
/* SDRAM Refresh Timer Register */
#define FMC_SDRTR MMIO32(FSMC_BASE + 0x154)
/* SDRAM Status Register */
#define FMC_SDSR MMIO32(FSMC_BASE + (uint32_t) 0x158)
/* --- FMC_SDCRx values ---------------------------------------------------- */
/* Bits [31:15]: Reserved. */
/* RPIPE: Read Pipe */
#define FMC_SDCR_RPIPE_SHIFT (1 << 13)
#define FMC_SDCR_RPIPE_MASK (3 << 13)
#define FMC_SDCR_RPIPE_NONE (0x0) /* No Delay */
#define FMC_SDCR_RPIPE_1CLK (1 << 13) /* one clock */
#define FMC_SDCR_RPIPE_2CLK (2 << 13) /* two clocks */
/* RBURST: Burst Read */
#define FMC_SDCR_RBURST (1 << 12)
/* SDCLK: SDRAM Clock Configuration */
#define FMC_SDCR_SDCLK_SHIFT (1 << 10)
#define FMC_SDCR_SDCLK_MASK (3 << 10)
#define FMC_SDCR_SDCLK_DISABLE (0)
#define FMC_SDCR_SDCLK_2HCLK (2 << 10)
#define FMC_SDCR_SDCLK_3HCLK (3 << 10)
/* WP: Write Protect */
#define FMC_SDCR_WP_ENABLE (1 << 9)
/* CAS: CAS Latency */
#define FMC_SDCR_CAS_SHIFT (1 << 7)
#define FMC_SDCR_CAS_1CYC (1 << 7)
#define FMC_SDCR_CAS_2CYC (2 << 7)
#define FMC_SDCR_CAS_3CYC (3 << 7)
/* NB: Number of Internal banks */
#define FMC_SDCR_NB2 0
#define FMC_SDCR_NB4 (1 << 6)
/* MWID: Memory width */
#define FMC_SDCR_MWID_SHIFT (1 << 4)
#define FMC_SDCR_MWID_8b (0 << 4)
#define FMC_SDCR_MWID_16b (1 << 4)
#define FMC_SDCR_MWID_32b (2 << 4)
/* NR: Number of rows */
#define FMC_SDCR_NR_SHIFT (1 << 2)
#define FMC_SDCR_NR_11 (0 << 2)
#define FMC_SDCR_NR_12 (1 << 2)
#define FMC_SDCR_NR_13 (2 << 2)
/* NC: Number of Columns */
#define FMC_SDCR_NC_SHIFT (1 << 0)
#define FMC_SDCR_NC_8 (0 << 0)
#define FMC_SDCR_NC_9 (1 << 0)
#define FMC_SDCR_NC_10 (2 << 0)
#define FMC_SDCR_NC_11 (3 << 0)
/* --- FMC_SDTRx values --------------------------------------------------- */
/* Bits [31:28]: Reserved. */
/* TRCD: Row to Column Delay */
#define FMC_SDTR_TRCD_SHIFT (1 << 24)
#define FMC_SDTR_TRCD_MASK (15 << 24)
/* TRP: Row Precharge Delay */
#define FMC_SDTR_TRP_SHIFT (1 << 20)
#define FMC_SDTR_TRP_MASK (15 << 20)
/* TWR: Recovery Delay */
#define FMC_SDTR_TWR_SHIFT (1 << 16)
#define FMC_SDTR_TWR_MASK (15 << 16)
/* TRC: Row Cycle Delay */
#define FMC_SDTR_TRC_SHIFT (1 << 12)
#define FMC_SDTR_TRC_MASK (15 << 12)
/* TRAS: Self Refresh Time */
#define FMC_SDTR_TRAS_SHIFT (1 << 8)
#define FMC_SDTR_TRAS_MASK (15 << 8)
/* TXSR: Exit Self-refresh Delay */
#define FMC_SDTR_TXSR_SHIFT (1 << 4)
#define FMC_SDTR_TXSR_MASK (15 << 4)
/* TRMD: Load Mode Register to Active */
#define FMC_SDTR_TMRD_SHIFT (1 << 0)
#define FMC_SDTR_TMRD_MASK (15 << 0)
/*
* Some config bits only count in CR1 or TR1, even if you
* are just configuring bank 2, so these masks let you copy
* out those bits after you have computed values for CR2 and
* TR2 and put them into CR1 and TR1
*/
#define FMC_SDTR_DNC_MASK ( FMC_SDTR_TRP_MASK| FMC_SDTR_TRC_MASK )
#define FMC_SDCR_DNC_MASK ( FMC_SDCR_SDCLK_MASK |\
FMC_SDCR_RPIPE_MASK |\
FMC_SDCR_RBURST )
/* --- FMC_SDCMR values --------------------------------------------------- */
/* Bits [31:22]: Reserved. */
/* MRD: Mode Register Definition */
#define FMC_SDCMR_MRD_SHIFT (1 << 9)
#define FMC_SDCMR_MRD_MASK (0x1fff << 9)
/* NRFS: Number of Auto-refresh */
#define FMC_SDCMR_NRFS_SHIFT (1 << 5)
#define FMC_SDCMR_NRFS_MASK (15 << 5)
/* CTB1: Command Target Bank 1 */
#define FMC_SDCMR_CTB1 (1 << 4)
/* CTB2: Command Target Bank 2 */
#define FMC_SDCMR_CTB2 (1 << 3)
/* MODE: Command Mode */
#define FMC_SDCMR_MODE_SHIFT (1 << 0)
#define FMC_SDCMR_MODE_MASK (7 << 0)
#define FMC_SDCMR_MODE_NORMAL 0
#define FMC_SDCMR_MODE_CLOCK_CONFIG_ENA 1
#define FMC_SDCMR_MODE_PALL 2
#define FMC_SDCMR_MODE_AUTO_REFRESH 3
#define FMC_SDCMR_MODE_LOAD_MODE_REGISTER 4
#define FMC_SDCMR_MODE_SELF_REFRESH 5
#define FMC_SDCMR_MODE_POWER_DOWN 6
/* --- FMC_SDRTR values ---------------------------------------------------- */
/* Bits [31:15]: Reserved. */
/* REIE: Refresh Error Interrupt Enable */
#define FMC_SDRTR_REIE (1 << 14)
/* COUNT: Refresh Timer Count */
#define FMC_SDRTR_COUNT_SHIFT (1 << 1)
#define FMC_SDRTR_COUNT_MASK (0x1fff << 1)
/* CRE: Clear Refresh Error Flag */
#define FMC_SDRTR_CRE (1 << 0)
/* --- FMC_SDSR values ---------------------------------------------------- */
/* Bits [31:6]: Reserved. */
/* BUSY: Set if the SDRAM is working on the command */
#define FMC_SDSR_BUSY (1 << 5)
/* MODES: Status modes */
#define FMC_SDSR_MODE_NORMAL 0
#define FMC_SDSR_MODE_SELF_REFRESH 1
#define FMC_SDSR_MODE_POWER_DOWN 2
/* Mode shift */
#define FMC_SDSR_MODE2_SHIFT ( 1 << 3)
#define FMC_SDSR_MODE1_SHIFT ( 1 << 1)
/* RE: Refresh Error */
#define FMC_SDSR_RE (1 << 0)
/* Helper function for setting the timing parameters */
struct sdram_timing {
int trcd; /* RCD Delay */
int trp; /* RP Delay */
int twr; /* Write Recovery Time */
int trc; /* Row Cycle Delay */
int tras; /* Self Refresh TIme */
int txsr; /* Exit Self Refresh Time */
int tmrd; /* Load to Active delay */
};
/* Mode register parameters */
#define SDRAM_MODE_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODE_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODE_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODE_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODE_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODE_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODE_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODE_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODE_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODE_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODE_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
enum fmc_sdram_bank { SDRAM_BANK1, SDRAM_BANK2, SDRAM_BOTH_BANKS };
enum fmc_sdram_command { SDRAM_CLK_CONF, SDRAM_NORMAL, SDRAM_PALL,
SDRAM_AUTO_REFRESH, SDRAM_LOAD_MODE,
SDRAM_SELF_REFRESH, SDRAM_POWER_DOWN };
/* Send an array of timing parameters (indices above) to create SDTR register value */
uint32_t sdram_timing(struct sdram_timing *t);
void sdram_command(enum fmc_sdram_bank bank, enum fmc_sdram_command cmd,
int autorefresh, int modereg);
#endif

14
include/libopencm3/stm32/f4/irq.json

@ -80,9 +80,19 @@
"otg_hs",
"dcmi",
"cryp",
"hash_rng"
"hash_rng",
"fpu",
"uart7",
"uart8",
"spi4",
"spi5",
"spi6",
"sai1",
"lcd_tft",
"lcd_tft_err",
"dma2d"
],
"partname_humanreadable": "STM32 F4 series",
"partname_doxygen": "STM32F4",
"includeguard": "LIBOPENCM3_STM32_F4_NVIC_H"
}
}

34
include/libopencm3/stm32/f4/memorymap.h

@ -29,8 +29,8 @@
#define PERIPH_BASE_APB1 (PERIPH_BASE + 0x00000)
#define PERIPH_BASE_APB2 (PERIPH_BASE + 0x10000)
#define PERIPH_BASE_AHB1 (PERIPH_BASE + 0x20000)
#define PERIPH_BASE_AHB2 0x50000000
#define PERIPH_BASE_AHB3 0x60000000
#define PERIPH_BASE_AHB2 0x50000000U
#define PERIPH_BASE_AHB3 0x60000000U
/* Register boundary addresses */
@ -48,10 +48,10 @@
#define RTC_BASE (PERIPH_BASE_APB1 + 0x2800)
#define WWDG_BASE (PERIPH_BASE_APB1 + 0x2c00)
#define IWDG_BASE (PERIPH_BASE_APB1 + 0x3000)
/* PERIPH_BASE_APB1 + 0x3400 (0x4000 3400 - 0x4000 37FF): Reserved */
#define I2S3_EXT_BASE (PERIPH_BASE_APB1 + 0x3400)
#define SPI2_I2S_BASE (PERIPH_BASE_APB1 + 0x3800)
#define SPI3_I2S_BASE (PERIPH_BASE_APB1 + 0x3c00)
/* PERIPH_BASE_APB1 + 0x4000 (0x4000 4000 - 0x4000 3FFF): Reserved */
#define I2S2_EXT_BASE (PERIPH_BASE_APB1 + 0x4000)
#define USART2_BASE (PERIPH_BASE_APB1 + 0x4400)
#define USART3_BASE (PERIPH_BASE_APB1 + 0x4800)
#define UART4_BASE (PERIPH_BASE_APB1 + 0x4c00)
@ -65,7 +65,9 @@
/* PERIPH_BASE_APB1 + 0x6C00 (0x4000 6C00 - 0x4000 6FFF): Reserved */
#define POWER_CONTROL_BASE (PERIPH_BASE_APB1 + 0x7000)
#define DAC_BASE (PERIPH_BASE_APB1 + 0x7400)
/* PERIPH_BASE_APB1 + 0x7800 (0x4000 7800 - 0x4000 FFFF): Reserved */
#define UART7_BASE (PERIPH_BASE_APB1 + 0x7800)
#define UART8_BASE (PERIPH_BASE_APB1 + 0x7c00)
/* PERIPH_BASE_APB1 + 0x7800 (0x4000 8000 - 0x4000 FFFF): Reserved */
/* APB2 */
#define TIM1_BASE (PERIPH_BASE_APB2 + 0x0000)
@ -82,13 +84,19 @@
#define SDIO_BASE (PERIPH_BASE_APB2 + 0x2C00)
/* PERIPH_BASE_APB2 + 0x2C00 (0x4001 2C00 - 0x4001 2FFF): Reserved */
#define SPI1_BASE (PERIPH_BASE_APB2 + 0x3000)
/* PERIPH_BASE_APB2 + 0x3400 (0x4001 3400 - 0x4001 37FF): Reserved */
#define SPI4_BASE (PERIPH_BASE_APB2 + 0x3400)
/* PERIPH_BASE_APB2 + 0x3500 (0x4001 3500 - 0x4001 37FF): Reserved */
#define SYSCFG_BASE (PERIPH_BASE_APB2 + 0x3800)
#define EXTI_BASE (PERIPH_BASE_APB2 + 0x3C00)
#define TIM9_BASE (PERIPH_BASE_APB2 + 0x4000)
#define TIM10_BASE (PERIPH_BASE_APB2 + 0x4400)
#define TIM11_BASE (PERIPH_BASE_APB2 + 0x4800)
/* PERIPH_BASE_APB2 + 0x4C00 (0x4001 4C00 - 0x4001 FFFF): Reserved */
/* PERIPH_BASE_APB2 + 0x4C00 (0x4001 4C00 - 0x4001 4FFF): Reserved */
#define SPI5_BASE (PERIPH_BASE_APB2 + 0x5000)
#define SPI6_BASE (PERIPH_BASE_APB2 + 0x5400)
#define SAI1_BASE (PERIPH_BASE_APB2 + 0x5800)
#define LCD_TFT_BASE (PERIPH_BASE_APB2 + 0x6800)
/* PERIPH_BASE_APB2 + 0x6C00 (0x4001 6C00 - 0x4001 FFFF): Reserved */
/* AHB1 */
#define GPIO_PORT_A_BASE (PERIPH_BASE_AHB1 + 0x0000)
@ -105,7 +113,7 @@
/* PERIPH_BASE_AHB1 + 0x3400 (0x4002 3400 - 0x4002 37FF): Reserved */
#define RCC_BASE (PERIPH_BASE_AHB1 + 0x3800)
#define FLASH_MEM_INTERFACE_BASE (PERIPH_BASE_AHB1 + 0x3C00)
#define BKPSRAM_BASE (PERIPH_BASE_AHB1 + 0x4000)
#define BKPSRAM_BASE (PERIPH_BASE_AHB1 + 0x4000)
/* PERIPH_BASE_AHB1 + 0x5000 (0x4002 5000 - 0x4002 5FFF): Reserved */
#define DMA1_BASE (PERIPH_BASE_AHB1 + 0x6000)
#define DMA2_BASE (PERIPH_BASE_AHB1 + 0x6400)
@ -118,16 +126,16 @@
/* AHB2 */
#define USB_OTG_FS_BASE (PERIPH_BASE_AHB2 + 0x00000)
/* PERIPH_BASE_AHB2 + 0x40000 (0x5004 0000 - 0x5004 FFFF): Reserved */
#define DCMI_BASE (PERIPH_BASE_AHB2 + 0x50000)
#define DCMI_BASE (PERIPH_BASE_AHB2 + 0x50000)
/* PERIPH_BASE_AHB2 + 0x50400 (0x5005 0400 - 0x5005 FFFF): Reserved */
#define CRYP_BASE (PERIPH_BASE_AHB2 + 0x60000)
#define HASH_BASE (PERIPH_BASE_AHB2 + 0x60400)
#define CRYP_BASE (PERIPH_BASE_AHB2 + 0x60000)
#define HASH_BASE (PERIPH_BASE_AHB2 + 0x60400)
/* PERIPH_BASE_AHB2 + 0x60C00 (0x5006 0C00 - 0x5006 07FF): Reserved */
#define RNG_BASE (PERIPH_BASE_AHB2 + 0x60800)
#define RNG_BASE (PERIPH_BASE_AHB2 + 0x60800)
/* PERIPH_BASE_AHB2 + 0x61000 (0x5006 1000 - 0x5FFF FFFF): Reserved */
/* AHB3 */
#define FSMC_BASE (PERIPH_BASE_AHB3 + 0x40000000)
#define FSMC_BASE (PERIPH_BASE_AHB3 + 0x40000000U)
/* PPIB */
#define DBGMCU_BASE (PPBI_BASE + 0x00042000)

7
include/libopencm3/stm32/f4/rcc.h

@ -310,9 +310,13 @@
/* --- RCC_AHB3ENR values ------------------------------------------------- */
#define RCC_AHB3ENR_FSMCEN (1 << 0)
/* Alternate now that F429 has DRAM controller as well */
#define RCC_AHB3ENR_FMCEN (1 << 0)
/* --- RCC_APB1ENR values ------------------------------------------------- */
#define RCC_APB1ENR_UART8EN (1 << 31)
#define RCC_APB1ENR_UART7EN (1 << 30)
#define RCC_APB1ENR_DACEN (1 << 29)
#define RCC_APB1ENR_PWREN (1 << 28)
#define RCC_APB1ENR_CAN2EN (1 << 26)
@ -339,10 +343,13 @@
/* --- RCC_APB2ENR values ------------------------------------------------- */
#define RCC_APB2ENR_SPI6EN (1 << 21)
#define RCC_APB2ENR_SPI5EN (1 << 20)
#define RCC_APB2ENR_TIM11EN (1 << 18)
#define RCC_APB2ENR_TIM10EN (1 << 17)
#define RCC_APB2ENR_TIM9EN (1 << 16)
#define RCC_APB2ENR_SYSCFGEN (1 << 14)
#define RCC_APB2ENR_SPI4EN (1 << 13)
#define RCC_APB2ENR_SPI1EN (1 << 12)
#define RCC_APB2ENR_SDIOEN (1 << 11)
#define RCC_APB2ENR_ADC3EN (1 << 10)

4
include/libopencm3/stm32/fsmc.h

@ -23,6 +23,10 @@
#include <libopencm3/stm32/memorymap.h>
#include <libopencm3/cm3/common.h>
#if defined(STM32F4)
# include <libopencm3/stm32/f4/fmc.h>
#endif
/* --- Convenience macros -------------------------------------------------- */
#define FSMC_BANK1_BASE 0x60000000 /* NOR / PSRAM */

2
lib/stm32/f4/Makefile

@ -50,7 +50,7 @@ OBJS += crc_common_all.o dac_common_all.o dma_common_f24.o \
OBJS += usb.o usb_standard.o usb_control.o usb_fx07_common.o \
usb_f107.o usb_f207.o
OBJS += mac.o phy.o mac_stm32fxx7.o phy_ksz8051mll.o
OBJS += mac.o phy.o mac_stm32fxx7.o phy_ksz8051mll.o fmc.o
VPATH += ../../usb:../:../../cm3:../common
VPATH += ../../ethernet

99
lib/stm32/f4/fmc.c

@ -0,0 +1,99 @@
/* vim: set noexpandtab ts=8:
*
* This file is part of the libopencm3 project.
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Utility functions for the SDRAM component of the FMC */
#include <stdint.h>
#include <libopencm3/stm32/fsmc.h>
/*
* Install various timing values into the correct place in the
* SDRAM Timing Control Register format.
*
* Note that the register is 'zero' based to save bits so 1 cycle
* is stored as '0'. This command takes actual cycles and adjusts
* by subtracting 1.
*/
uint32_t
sdram_timing(struct sdram_timing *t) {
uint32_t result;
result = 0;
result |= ((t->trcd - 1) & 0xf) * FMC_SDTR_TRCD_SHIFT;
result |= ((t->trp - 1) & 0xf) * FMC_SDTR_TRP_SHIFT;
result |= ((t->twr - 1) & 0xf) * FMC_SDTR_TWR_SHIFT;
result |= ((t->trc - 1) & 0xf) * FMC_SDTR_TRC_SHIFT;
result |= ((t->tras - 1) & 0xf) * FMC_SDTR_TRAS_SHIFT;
result |= ((t->txsr - 1) & 0xf) * FMC_SDTR_TXSR_SHIFT;
result |= ((t->tmrd - 1) & 0xf) * FMC_SDTR_TMRD_SHIFT;
return result;
}
/*
* Send a command to the SDRAM controller, wait until it is not
* busy before sending. This allows you to chain sending commands
* and the code will pause as needed between them.
*/
void
sdram_command(enum fmc_sdram_bank bank,
enum fmc_sdram_command cmd, int autorefresh, int modereg) {
uint32_t tmp_reg = 0;
switch (bank) {
case SDRAM_BANK1:
tmp_reg = FMC_SDCMR_CTB1;
break;
case SDRAM_BANK2:
tmp_reg = FMC_SDCMR_CTB2;
break;
case SDRAM_BOTH_BANKS:
tmp_reg = FMC_SDCMR_CTB1 | FMC_SDCMR_CTB2;
break;
}
tmp_reg |= autorefresh * FMC_SDCMR_NRFS_SHIFT;
tmp_reg |= modereg * FMC_SDCMR_MRD_SHIFT;
switch (cmd) {
case SDRAM_CLK_CONF:
tmp_reg |= FMC_SDCMR_MODE_CLOCK_CONFIG_ENA;
break;
case SDRAM_AUTO_REFRESH:
tmp_reg |= FMC_SDCMR_MODE_AUTO_REFRESH;
break;
case SDRAM_LOAD_MODE:
tmp_reg |= FMC_SDCMR_MODE_LOAD_MODE_REGISTER;
break;
case SDRAM_PALL:
tmp_reg |= FMC_SDCMR_MODE_PALL;
break;
case SDRAM_SELF_REFRESH:
tmp_reg |= FMC_SDCMR_MODE_SELF_REFRESH;
break;
case SDRAM_POWER_DOWN:
tmp_reg |= FMC_SDCMR_MODE_POWER_DOWN;
break;
case SDRAM_NORMAL:
default:
break;
}
/* Wait for the next chance to talk to the controller */
while (FMC_SDSR & FMC_SDSR_BUSY) ;
/* Send the next command */
FMC_SDCMR = tmp_reg;
}
Loading…
Cancel
Save