summaryrefslogtreecommitdiffstats
path: root/bsps/arm/stm32f4
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 10:35:35 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 13:52:14 +0200
commit99648958668d3a33ee57974479b36201fe303f34 (patch)
tree6f27ea790e2823c6156e71219a4f54680263fac6 /bsps/arm/stm32f4
parentbsps: Move start files to bsps (diff)
downloadrtems-99648958668d3a33ee57974479b36201fe303f34.tar.bz2
bsps: Move startup files to bsps
Adjust build support files to new directory layout. This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/arm/stm32f4')
-rw-r--r--bsps/arm/stm32f4/start/bsp_specs9
-rw-r--r--bsps/arm/stm32f4/start/bspreset.c27
-rw-r--r--bsps/arm/stm32f4/start/bspstart.c303
-rw-r--r--bsps/arm/stm32f4/start/bspstarthook.c29
-rw-r--r--bsps/arm/stm32f4/start/io.c249
-rw-r--r--bsps/arm/stm32f4/start/linkcmds.stm32f105rc24
-rw-r--r--bsps/arm/stm32f4/start/linkcmds.stm32f424
-rw-r--r--bsps/arm/stm32f4/start/rcc.c76
-rw-r--r--bsps/arm/stm32f4/start/start-config-io.c85
9 files changed, 826 insertions, 0 deletions
diff --git a/bsps/arm/stm32f4/start/bsp_specs b/bsps/arm/stm32f4/start/bsp_specs
new file mode 100644
index 0000000000..47dd31d46b
--- /dev/null
+++ b/bsps/arm/stm32f4/start/bsp_specs
@@ -0,0 +1,9 @@
+%rename endfile old_endfile
+%rename startfile old_startfile
+
+*startfile:
+%{!qrtems: %(old_startfile)} \
+%{!nostdlib: %{qrtems: crti.o%s crtbegin.o%s}}
+
+*endfile:
+%{!qrtems: %(old_endfiles)} %{qrtems: crtend.o%s crtn.o%s}
diff --git a/bsps/arm/stm32f4/start/bspreset.c b/bsps/arm/stm32f4/start/bspreset.c
new file mode 100644
index 0000000000..ff46d4f86b
--- /dev/null
+++ b/bsps/arm/stm32f4/start/bspreset.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <bsp/bootcard.h>
+
+void bsp_reset(void)
+{
+ rtems_interrupt_level level;
+
+ (void) level;
+ rtems_interrupt_disable(level);
+
+ while (1);
+}
diff --git a/bsps/arm/stm32f4/start/bspstart.c b/bsps/arm/stm32f4/start/bspstart.c
new file mode 100644
index 0000000000..8d4bf6b82b
--- /dev/null
+++ b/bsps/arm/stm32f4/start/bspstart.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/io.h>
+#include <bsp/irq.h>
+#include <bsp/bootcard.h>
+#include <bsp/irq-generic.h>
+#include <assert.h>
+#include <bsp/stm32f4.h>
+
+#ifdef STM32F4_FAMILY_F4XXXX
+
+#include <bsp/stm32f4xxxx_rcc.h>
+#include <bsp/stm32f4xxxx_flash.h>
+
+static rtems_status_code set_system_clk(
+ uint32_t sys_clk,
+ uint32_t hse_clk,
+ uint32_t hse_flag
+);
+
+static void init_main_osc( void )
+{
+ volatile stm32f4_rcc *rcc = STM32F4_RCC;
+ rtems_status_code status;
+
+ /* Revert to reset values */
+ rcc->cr |= RCC_CR_HSION; /* turn on HSI */
+
+ while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ;
+
+ rcc->cfgr &= 0x00000300; /* all prescalers to 0, clock source to HSI */
+
+ rcc->cr &= 0xF0F0FFFD; /* turn off all clocks and PLL except HSI */
+
+ status = set_system_clk( STM32F4_SYSCLK / 1000000L,
+ STM32F4_HSE_OSCILLATOR / 1000000L,
+ 1 );
+
+ assert( rtems_is_status_successful( status ) );
+}
+
+/**
+ * @brief Sets up clocks configuration.
+ *
+ * Set up clocks configuration to achieve desired system clock
+ * as close as possible with simple math.
+ *
+ * Limitations:
+ * It is assumed that 1MHz resolution is enough.
+ * Best fits for the clocks are achieved with multiplies of 42MHz.
+ * Even though APB1, APB2 and AHB are calculated user is still required
+ * to provide correct values for the bsp configuration for the:
+ * STM32F4_PCLK1
+ * STM32F4_PCLK2
+ * STM32F4_HCLK
+ * as those are used for the peripheral clocking calculations.
+ *
+ * @param sys_clk Desired system clock in MHz.
+ * @param hse_clk External clock speed in MHz.
+ * @param hse_flag Flag determining which clock source to use, 1 for HSE,
+ * 0 for HSI.
+ *
+ * @retval RTEMS_SUCCESSFUL Configuration has been succesfully aplied for the
+ * requested clock speed.
+ * @retval RTEMS_TIMEOUT HSE clock didn't start or PLL didn't lock.
+ * @retval RTEMS_INVALID_NUMBER Requested clock speed is out of range.
+ */
+static rtems_status_code set_system_clk(
+ uint32_t sys_clk,
+ uint32_t hse_clk,
+ uint32_t hse_flag
+)
+{
+ volatile stm32f4_rcc *rcc = STM32F4_RCC;
+ volatile stm32f4_flash *flash = STM32F4_FLASH;
+ long timeout = 0;
+
+ int src_clk = 0;
+
+ uint32_t pll_m = 0;
+ uint32_t pll_n = 0;
+ uint32_t pll_p = 0;
+ uint32_t pll_q = 0;
+
+ uint32_t ahbpre = 0;
+ uint32_t apbpre1 = 0;
+ uint32_t apbpre2 = 0;
+
+ if ( sys_clk == 16 && hse_clk != 16 ) {
+ /* Revert to reset values */
+ rcc->cr |= RCC_CR_HSION; /* turn on HSI */
+
+ while ( !( rcc->cr & RCC_CR_HSIRDY ) ) ;
+
+ /* all prescalers to 0, clock source to HSI */
+ rcc->cfgr &= 0x00000300 | RCC_CFGR_SW_HSI;
+ rcc->cr &= 0xF0F0FFFD; /* turn off all clocks and PLL except HSI */
+ flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */
+
+ return RTEMS_SUCCESSFUL;
+ }
+
+ if ( sys_clk == hse_clk ) {
+ /* Revert to reset values */
+ rcc->cr |= RCC_CR_HSEON; /* turn on HSE */
+ timeout = 400;
+
+ while ( !( rcc->cr & RCC_CR_HSERDY ) && --timeout ) ;
+
+ assert( timeout != 0 );
+
+ if ( timeout == 0 ) {
+ return RTEMS_TIMEOUT;
+ }
+
+ /* all prescalers to 0, clock source to HSE */
+ rcc->cfgr &= 0x00000300;
+ rcc->cfgr |= RCC_CFGR_SW_HSE;
+ /* turn off all clocks and PLL except HSE */
+ rcc->cr &= 0xF0F0FFFC | RCC_CR_HSEON;
+ flash->acr = 0; /* slow clock so no cache, no prefetch, no latency */
+
+ return RTEMS_SUCCESSFUL;
+ }
+
+ /*
+ * Lets use 1MHz input for PLL so we get higher VCO output
+ * this way we get better value for the PLL_Q divader for the USB
+ *
+ * Though you might want to use 2MHz as per CPU specification:
+ *
+ * Caution:The software has to set these bits correctly to ensure
+ * that the VCO input frequency ranges from 1 to 2 MHz.
+ * It is recommended to select a frequency of 2 MHz to limit PLL jitter.
+ */
+
+ if ( sys_clk > 180 ) {
+ return RTEMS_INVALID_NUMBER;
+ } else if ( sys_clk >= 96 ) {
+ pll_n = sys_clk << 1;
+ pll_p = RCC_PLLCFGR_PLLP_BY_2;
+ } else if ( sys_clk >= 48 ) {
+ pll_n = sys_clk << 2;
+ pll_p = RCC_PLLCFGR_PLLP_BY_4;
+ } else if ( sys_clk >= 24 ) {
+ pll_n = sys_clk << 3;
+ pll_p = RCC_PLLCFGR_PLLP_BY_8;
+ } else {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ if ( hse_clk == 0 || hse_flag == 0 ) {
+ src_clk = 16;
+ hse_flag = 0;
+ } else {
+ src_clk = hse_clk;
+ }
+
+ pll_m = src_clk; /* divide by the oscilator speed in MHz */
+
+ /* pll_q is a prescaler from VCO for the USB OTG FS, SDIO and RNG,
+ * best if results in the 48MHz for the USB
+ */
+ pll_q = ( (long) ( src_clk * pll_n ) ) / pll_m / 48;
+
+ if ( pll_q < 2 ) {
+ pll_q = 2;
+ }
+
+ /* APB1 prescaler, APB1 clock must be < 42MHz */
+ apbpre1 = ( sys_clk * 100 ) / 42;
+
+ if ( apbpre1 <= 100 ) {
+ apbpre1 = RCC_CFGR_PPRE1_BY_1;
+ } else if ( apbpre1 <= 200 ) {
+ apbpre1 = RCC_CFGR_PPRE1_BY_2;
+ } else if ( apbpre1 <= 400 ) {
+ apbpre1 = RCC_CFGR_PPRE1_BY_4;
+ } else if ( apbpre1 <= 800 ) {
+ apbpre1 = RCC_CFGR_PPRE1_BY_8;
+ } else if ( apbpre1 ) {
+ apbpre1 = RCC_CFGR_PPRE1_BY_16;
+ }
+
+ /* APB2 prescaler, APB2 clock must be < 84MHz */
+ apbpre2 = ( sys_clk * 100 ) / 84;
+
+ if ( apbpre2 <= 100 ) {
+ apbpre2 = RCC_CFGR_PPRE2_BY_1;
+ } else if ( apbpre2 <= 200 ) {
+ apbpre2 = RCC_CFGR_PPRE2_BY_2;
+ } else if ( apbpre2 <= 400 ) {
+ apbpre2 = RCC_CFGR_PPRE2_BY_4;
+ } else if ( apbpre2 <= 800 ) {
+ apbpre2 = RCC_CFGR_PPRE2_BY_8;
+ } else {
+ apbpre2 = RCC_CFGR_PPRE2_BY_16;
+ }
+
+ rcc->cr |= RCC_CR_HSION; /* turn on HSI */
+
+ while ( ( !( rcc->cr & RCC_CR_HSIRDY ) ) ) ;
+
+ /* all prescalers to 0, clock source to HSI */
+ rcc->cfgr &= 0x00000300;
+ rcc->cfgr |= RCC_CFGR_SW_HSI;
+
+ while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_HSI ) ) ;
+
+ /* turn off PLL */
+ rcc->cr &= ~( RCC_CR_PLLON | RCC_CR_PLLRDY );
+
+ /* turn on HSE */
+ if ( hse_flag ) {
+ rcc->cr |= RCC_CR_HSEON;
+ timeout = 400;
+
+ while ( ( !( rcc->cr & RCC_CR_HSERDY ) ) && timeout-- ) ;
+
+ assert( timeout != 0 );
+
+ if ( timeout == 0 ) {
+ return RTEMS_TIMEOUT;
+ }
+ }
+
+ rcc->pllcfgr &= 0xF0BC8000; /* clear PLL prescalers */
+
+ /* set pll parameters */
+ rcc->pllcfgr |= RCC_PLLCFGR_PLLM( pll_m ) | /* input divider */
+ RCC_PLLCFGR_PLLN( pll_n ) | /* multiplier */
+ pll_p | /* output divider from table */
+ /* HSE v HSI */
+ ( hse_flag ? RCC_PLLCFGR_PLLSRC_HSE : RCC_PLLCFGR_PLLSRC_HSI )
+ |
+ RCC_PLLCFGR_PLLQ( pll_q ); /* PLLQ divider */
+
+ /* set prescalers for the internal busses */
+ rcc->cfgr |= apbpre1 |
+ apbpre2 |
+ ahbpre;
+
+ /*
+ * Set flash parameters, hard coded for now for fast system clocks.
+ * TODO implement some math to use flash on as low latancy as possible
+ */
+ flash->acr = STM32F4_FLASH_ACR_LATENCY( 5 ) | /* latency */
+ STM32F4_FLASH_ACR_ICEN | /* instruction cache */
+ STM32F4_FLASH_ACR_DCEN | /* data cache */
+ STM32F4_FLASH_ACR_PRFTEN;
+
+ /* turn on PLL */
+ rcc->cr |= RCC_CR_PLLON;
+ timeout = 40000;
+
+ while ( ( !( rcc->cr & RCC_CR_PLLRDY ) ) && --timeout ) ;
+
+ assert( timeout != 0 );
+
+ if ( timeout == 0 ) {
+ return RTEMS_TIMEOUT;
+ }
+
+ /* clock source to PLL */
+ rcc->cfgr = ( rcc->cfgr & ~RCC_CFGR_SW_MSK ) | RCC_CFGR_SW_PLL;
+
+ while ( ( ( rcc->cfgr & RCC_CFGR_SWS_MSK ) != RCC_CFGR_SWS_PLL ) ) ;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#endif /* STM32F4_FAMILY_F4XXXX */
+
+#ifdef STM32F4_FAMILY_F10XXX
+
+static void init_main_osc( void )
+{
+
+}
+
+#endif /* STM32F4_FAMILY_F10XXX */
+
+void bsp_start( void )
+{
+ init_main_osc();
+
+ stm32f4_gpio_set_config_array( &stm32f4_start_config_gpio[ 0 ] );
+
+ bsp_interrupt_initialize();
+}
diff --git a/bsps/arm/stm32f4/start/bspstarthook.c b/bsps/arm/stm32f4/start/bspstarthook.c
new file mode 100644
index 0000000000..8e9295b853
--- /dev/null
+++ b/bsps/arm/stm32f4/start/bspstarthook.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/start.h>
+
+void BSP_START_TEXT_SECTION bsp_start_hook_0(void)
+{
+ /* Do nothing */
+}
+
+void BSP_START_TEXT_SECTION bsp_start_hook_1(void)
+{
+ bsp_start_copy_sections();
+ bsp_start_clear_bss();
+
+ /* At this point we can use objects outside the .start section */
+}
diff --git a/bsps/arm/stm32f4/start/io.c b/bsps/arm/stm32f4/start/io.c
new file mode 100644
index 0000000000..dcbdb70ff5
--- /dev/null
+++ b/bsps/arm/stm32f4/start/io.c
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/io.h>
+#include <bsp/rcc.h>
+#include <bsp/stm32f4.h>
+
+#include <rtems.h>
+
+RTEMS_STATIC_ASSERT(sizeof(stm32f4_gpio_config) == 4, size_of_config);
+
+void stm32f4_gpio_set_clock(int pin, bool set)
+{
+ int port = STM32F4_GPIO_PORT_OF_PIN(pin);
+ stm32f4_rcc_index index = STM32F4_RCC_GPIOA + port;
+
+ stm32f4_rcc_set_clock(index, set);
+}
+
+static void clear_and_set(
+ volatile uint32_t *reg,
+ unsigned index,
+ unsigned width,
+ uint32_t set
+)
+{
+ uint32_t mask = (1U << width) - 1U;
+ unsigned shift = width * index;
+ uint32_t val = *reg;
+
+ val &= ~(mask << shift);
+ val |= set << shift;
+
+ *reg = val;
+}
+
+#ifdef STM32F4_FAMILY_F10XXX
+#define STM32F4_AFIO_REMAP_ENTRY(mod, afio_reg_v, start_v, width_v, value_v) \
+ [mod] = { \
+ .afio_reg = afio_reg_v, \
+ .start = start_v, \
+ .width = width_v, \
+ .value = value_v, \
+ .reserved = 0 \
+ }
+
+typedef struct {
+ uint16_t afio_reg : 3;
+ uint16_t start : 5;
+ uint16_t width : 2;
+ uint16_t value : 3;
+ uint16_t reserved : 3;
+} stm32f4_afio_remap_entry;
+
+static const stm32f4_afio_remap_entry stm32f4_afio_remap_table [] = {
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_DONT_CHANGE, 0, 0, 0, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI1_0, 1, 0, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI1_1, 1, 0, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_I2C1_0, 1, 1, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_I2C1_1, 1, 1, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART1_0, 1, 2, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART1_1, 1, 2, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART2_0, 1, 3, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART2_1, 1, 3, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_0, 1, 4, 2, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_1, 1, 4, 2, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_USART3_3, 1, 4, 2, 3),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_0, 1, 6, 2, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_1, 1, 6, 2, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_3, 1, 6, 2, 3),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_0, 1, 8, 2, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_1, 1, 8, 2, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_2, 1, 8, 2, 2),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2_3, 1, 8, 2, 3),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_0, 1, 10, 2, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_2, 1, 10, 2, 2),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM3_3, 1, 10, 2, 3),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM4_0, 1, 12, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM4_1, 1, 12, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_0, 1, 13, 2, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_2, 1, 13, 2, 2),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN1_3, 1, 13, 2, 3),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PD01_0, 1, 15, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PD01_1, 1, 15, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM5CH4_0, 1, 16, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM5CH4_1, 1, 16, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGINJ_0, 1, 17, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGINJ_1, 1, 17, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGREG_0, 1, 18, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC1_ETRGREG_1, 1, 18, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGINJ_0, 1, 19, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGINJ_1, 1, 19, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGREG_0, 1, 20, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ADC2_ETRGREG_1, 1, 20, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ETH_0, 1, 21, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_ETH_1, 1, 21, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN2_0, 1, 22, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CAN2_1, 1, 22, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MII_RMII_0, 1, 23, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MII_RMII_1, 1, 23, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_0, 1, 24, 3, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_1, 1, 24, 3, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_2, 1, 24, 3, 2),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SWJ_4, 1, 24, 3, 4),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI3_0, 1, 28, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_SPI3_1, 1, 28, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2ITR1_0, 1, 29, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM2ITR1_1, 1, 29, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PTP_PPS_0, 1, 30, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_PTP_PPS_1, 1, 30, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM15_0, 6, 0, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM15_1, 6, 0, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM16_0, 6, 1, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM16_1, 6, 1, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM17_0, 6, 2, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM17_1, 6, 2, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CEC_0, 6, 3, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_CEC_1, 6, 3, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_DMA_0, 6, 4, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM1_DMA_1, 6, 4, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM9_0, 6, 5, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM9_1, 6, 5, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM10_0, 6, 6, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM10_1, 6, 6, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM11_0, 6, 7, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM11_1, 6, 7, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM13_0, 6, 8, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM13_1, 6, 8, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM14_0, 6, 9, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM14_1, 6, 9, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_FSMC_0, 6, 10, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_FSMC_1, 6, 10, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM67_DAC_DMA_0, 6, 11, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM67_DAC_DMA_1, 6, 11, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM12_0, 6, 12, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_TIM12_1, 6, 12, 1, 1),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MISC_0, 6, 13, 1, 0),
+ STM32F4_AFIO_REMAP_ENTRY(STM32F4_GPIO_REMAP_MISC_1, 6, 13, 1, 1),
+};
+
+static void set_remap_config(stm32f4_gpio_remap remap)
+{
+ if(remap != STM32F4_GPIO_REMAP_DONT_CHANGE)
+ {
+ stm32f4_afio_remap_entry entry = stm32f4_afio_remap_table[remap];
+ volatile stm32f4_afio *afio = STM32F4_AFIO;
+ volatile uint32_t *reg = ((uint32_t*) afio) + entry.afio_reg;
+ uint32_t mask = (1 << entry.width) - 1;
+ uint32_t value = *reg;
+
+ value &= mask << entry.start;
+ value |= entry.value << entry.start;
+
+ *reg = value;
+ }
+}
+
+#endif /* STM32F4_FAMILY_F10XXX */
+
+static void set_config(unsigned pin, const stm32f4_gpio_config *config)
+{
+ unsigned port = STM32F4_GPIO_PORT_OF_PIN(pin);
+ volatile stm32f4_gpio *gpio = STM32F4_GPIO(port);
+ unsigned index = STM32F4_GPIO_INDEX_OF_PIN(pin);
+ rtems_interrupt_level level;
+ int set_or_clear_offset = config->fields.output ? 0 : 16;
+#ifdef STM32F4_FAMILY_F4XXXX
+ unsigned af_reg = index >> 3;
+ unsigned af_index = index & 0x7;
+
+ rtems_interrupt_disable(level);
+ gpio->bsrr = 1U << (index + set_or_clear_offset);
+ clear_and_set(&gpio->pupdr, index, 2, config->fields.pupd);
+ clear_and_set(&gpio->otyper, index, 1, config->fields.otype);
+ clear_and_set(&gpio->ospeedr, index, 2, config->fields.ospeed);
+ clear_and_set(&gpio->afr [af_reg], af_index, 4, config->fields.af);
+ clear_and_set(&gpio->moder, index, 2, config->fields.mode);
+ rtems_interrupt_enable(level);
+
+#endif /* STM32F4_FAMILY_F4XXXX */
+#ifdef STM32F4_FAMILY_F10XXX
+ unsigned cr_reg = index >> 3;
+ unsigned cr_index = index & 0x7;
+
+ rtems_interrupt_disable(level);
+ gpio->bsrr = 1U << (index + set_or_clear_offset);
+ clear_and_set(&gpio->cr[cr_reg], cr_index, 4,
+ (config->fields.cnf << 2) | config->fields.mode);
+ set_remap_config(config->fields.remap);
+ rtems_interrupt_enable(level);
+
+#endif /* STM32F4_FAMILY_F10XXX */
+}
+
+void stm32f4_gpio_set_config(const stm32f4_gpio_config *config)
+{
+ int current = config->fields.pin_first;
+ int last = config->fields.pin_last;
+
+#ifdef STM32F4_FAMILY_F10XXX
+ stm32f4_rcc_set_clock(STM32F4_RCC_AFIO, true);
+#endif /* STM32F4_FAMILY_F10XXX */
+
+ while (current <= last) {
+ stm32f4_gpio_set_clock(current, true);
+ set_config(current, config);
+ ++current;
+ }
+}
+
+void stm32f4_gpio_set_config_array(const stm32f4_gpio_config *configs)
+{
+ stm32f4_gpio_config terminal = STM32F4_GPIO_CONFIG_TERMINAL;
+
+ while (configs->value != terminal.value) {
+ stm32f4_gpio_set_config(configs);
+ ++configs;
+ }
+}
+
+void stm32f4_gpio_set_output(int pin, bool set)
+{
+ int port = STM32F4_GPIO_PORT_OF_PIN(pin);
+ volatile stm32f4_gpio *gpio = STM32F4_GPIO(port);
+ int index = STM32F4_GPIO_INDEX_OF_PIN(pin);
+ int set_or_clear_offset = set ? 0 : 16;
+
+ gpio->bsrr = 1U << (index + set_or_clear_offset);
+}
+
+bool stm32f4_gpio_get_input(int pin)
+{
+ int port = STM32F4_GPIO_PORT_OF_PIN(pin);
+ volatile stm32f4_gpio *gpio = STM32F4_GPIO(port);
+ int index = STM32F4_GPIO_INDEX_OF_PIN(pin);
+
+ return (gpio->idr & (1U << index)) != 0;
+}
diff --git a/bsps/arm/stm32f4/start/linkcmds.stm32f105rc b/bsps/arm/stm32f4/start/linkcmds.stm32f105rc
new file mode 100644
index 0000000000..d3ea200f2b
--- /dev/null
+++ b/bsps/arm/stm32f4/start/linkcmds.stm32f105rc
@@ -0,0 +1,24 @@
+MEMORY {
+ RAM_INT : ORIGIN = 0x20000000, LENGTH = 64k
+ ROM_INT : ORIGIN = 0x00000000, LENGTH = 256k
+}
+
+REGION_ALIAS ("REGION_START", ROM_INT);
+REGION_ALIAS ("REGION_VECTOR", RAM_INT);
+REGION_ALIAS ("REGION_TEXT", ROM_INT);
+REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_RODATA", ROM_INT);
+REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_DATA", RAM_INT);
+REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT);
+REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_FAST_DATA", RAM_INT);
+REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_BSS", RAM_INT);
+REGION_ALIAS ("REGION_WORK", RAM_INT);
+REGION_ALIAS ("REGION_STACK", RAM_INT);
+REGION_ALIAS ("REGION_NOCACHE", RAM_INT);
+REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT);
+
+INCLUDE linkcmds.armv7m
diff --git a/bsps/arm/stm32f4/start/linkcmds.stm32f4 b/bsps/arm/stm32f4/start/linkcmds.stm32f4
new file mode 100644
index 0000000000..1d16cfdde9
--- /dev/null
+++ b/bsps/arm/stm32f4/start/linkcmds.stm32f4
@@ -0,0 +1,24 @@
+MEMORY {
+ RAM_INT : ORIGIN = 0x20000000, LENGTH = 128k
+ ROM_INT : ORIGIN = 0x00000000, LENGTH = 1M
+}
+
+REGION_ALIAS ("REGION_START", ROM_INT);
+REGION_ALIAS ("REGION_VECTOR", RAM_INT);
+REGION_ALIAS ("REGION_TEXT", ROM_INT);
+REGION_ALIAS ("REGION_TEXT_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_RODATA", ROM_INT);
+REGION_ALIAS ("REGION_RODATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_DATA", RAM_INT);
+REGION_ALIAS ("REGION_DATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_FAST_TEXT", RAM_INT);
+REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_FAST_DATA", RAM_INT);
+REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM_INT);
+REGION_ALIAS ("REGION_BSS", RAM_INT);
+REGION_ALIAS ("REGION_WORK", RAM_INT);
+REGION_ALIAS ("REGION_STACK", RAM_INT);
+REGION_ALIAS ("REGION_NOCACHE", RAM_INT);
+REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM_INT);
+
+INCLUDE linkcmds.armv7m
diff --git a/bsps/arm/stm32f4/start/rcc.c b/bsps/arm/stm32f4/start/rcc.c
new file mode 100644
index 0000000000..ed0b2f1610
--- /dev/null
+++ b/bsps/arm/stm32f4/start/rcc.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/rcc.h>
+#include <bsp/stm32f4.h>
+
+#include <rtems.h>
+
+static void rcc_set(
+ stm32f4_rcc_index index,
+ bool set,
+ volatile uint32_t *regs
+)
+{
+ int reg = index >> 5;
+ uint32_t one = 1;
+ uint32_t bit = one << (index & 0x1f);
+ rtems_interrupt_level level;
+ uint32_t val;
+
+ rtems_interrupt_disable(level);
+ val = regs [reg];
+ if (set) {
+ val |= bit;
+ } else {
+ val &= ~bit;
+ }
+ regs [reg] = val;
+ rtems_interrupt_enable(level);
+}
+
+void stm32f4_rcc_reset(stm32f4_rcc_index index)
+{
+ stm32f4_rcc_set_reset(index, true);
+ stm32f4_rcc_set_reset(index, false);
+}
+
+void stm32f4_rcc_set_reset(stm32f4_rcc_index index, bool set)
+{
+ volatile stm32f4_rcc *rcc = STM32F4_RCC;
+
+#ifdef STM32F4_FAMILY_F4XXXX
+ rcc_set(index, set, &rcc->ahbrstr [0]);
+#endif/* STM32F4_FAMILY_F4XXXX */
+#ifdef STM32F4_FAMILY_F10XXX
+ /* The first register is missing for the reset-block */
+ rcc_set(index, set, &rcc->cir);
+#endif /* STM32F4_FAMILY_F10XXX */
+}
+
+void stm32f4_rcc_set_clock(stm32f4_rcc_index index, bool set)
+{
+ volatile stm32f4_rcc *rcc = STM32F4_RCC;
+
+ rcc_set(index, set, &rcc->ahbenr [0]);
+}
+
+#ifdef STM32F4_FAMILY_F4XXXX
+void stm32f4_rcc_set_low_power_clock(stm32f4_rcc_index index, bool set)
+{
+ volatile stm32f4_rcc *rcc = STM32F4_RCC;
+
+ rcc_set(index, set, &rcc->ahblpenr [0]);
+}
+#endif /* STM32F4_FAMILY_F4XXXX */
diff --git a/bsps/arm/stm32f4/start/start-config-io.c b/bsps/arm/stm32f4/start/start-config-io.c
new file mode 100644
index 0000000000..712fd0705b
--- /dev/null
+++ b/bsps/arm/stm32f4/start/start-config-io.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012 Sebastian Huber. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Obere Lagerstr. 30
+ * 82178 Puchheim
+ * Germany
+ * <rtems@embedded-brains.de>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/io.h>
+#include <bsp.h>
+
+const stm32f4_gpio_config stm32f4_start_config_gpio [] = {
+#ifdef STM32F4_FAMILY_F4XXXX
+ #ifdef STM32F4_ENABLE_USART_1
+ STM32F4_PIN_USART1_TX_PA9,
+ STM32F4_PIN_USART1_RX_PA10,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_2
+ STM32F4_PIN_USART2_TX_PA2,
+ STM32F4_PIN_USART2_RX_PA3,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_3
+ STM32F4_PIN_USART3_TX_PD8,
+ STM32F4_PIN_USART3_RX_PD9,
+ #endif
+ #ifdef STM32F4_ENABLE_UART_4
+ STM32F4_PIN_UART4_TX_PA0,
+ STM32F4_PIN_UART4_RX_PA1,
+ #endif
+ #ifdef STM32F4_ENABLE_UART_5
+ STM32F4_PIN_UART5_TX_PC12,
+ STM32F4_PIN_UART5_RX_PD2,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_6
+ STM32F4_PIN_USART6_TX_PC6,
+ STM32F4_PIN_USART6_RX_PC7,
+ #endif
+ #ifdef STM32F4_ENABLE_I2C1
+ #error Not implemented.
+ #endif
+ #ifdef STM32F4_ENABLE_I2C2
+ #error Not implemented.
+ #endif
+#endif /* STM32F4_FAMILY_F4XXXX */
+#ifdef STM32F4_FAMILY_F10XXX
+ #ifdef STM32F4_ENABLE_USART_1
+ STM32F4_PIN_USART1_TX_MAP_0,
+ STM32F4_PIN_USART1_RX_MAP_0,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_2
+ STM32F4_PIN_USART2_TX_MAP_0,
+ STM32F4_PIN_USART2_RX_MAP_0,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_3
+ STM32F4_PIN_USART3_TX_MAP_0,
+ STM32F4_PIN_USART3_RX_MAP_0,
+ #endif
+ #ifdef STM32F4_ENABLE_UART_4
+ STM32F4_PIN_UART4_TX,
+ STM32F4_PIN_UART4_RX,
+ #endif
+ #ifdef STM32F4_ENABLE_UART_5
+ STM32F4_PIN_UART5_TX,
+ STM32F4_PIN_UART5_RX,
+ #endif
+ #ifdef STM32F4_ENABLE_USART_6
+ #error STM32F10XXX has no USART 6
+ #endif
+ #ifdef STM32F4_ENABLE_I2C1
+ STM32F4_PIN_I2C1_SCL_MAP0,
+ STM32F4_PIN_I2C1_SDA_MAP0,
+ #endif
+ #ifdef STM32F4_ENABLE_I2C2
+ STM32F4_PIN_I2C2_SCL,
+ STM32F4_PIN_I2C2_SDA,
+ #endif
+#endif /* STM32F4_FAMILY_F10XXX */
+ STM32F4_GPIO_CONFIG_TERMINAL
+};