summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/arm/lm3s69xx/startup
diff options
context:
space:
mode:
authorEugeniy Meshcheryakov <eugen@debian.org>2013-04-26 11:03:59 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-04-26 11:03:59 +0200
commitf22bba3cb43182374bbddfad4e28545f89bd14ed (patch)
treed19f5e147e3b3adf8c75782c676a25f804fb9ca5 /c/src/lib/libbsp/arm/lm3s69xx/startup
parentlibcsupport: Delete libc_wrapup() (diff)
downloadrtems-f22bba3cb43182374bbddfad4e28545f89bd14ed.tar.bz2
bsp/lm3s69xx: New BSP variants
Add support for LM3S3749.
Diffstat (limited to 'c/src/lib/libbsp/arm/lm3s69xx/startup')
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c8
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c101
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/io.c144
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s374928
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s69654
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu28
-rw-r--r--c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c106
7 files changed, 406 insertions, 13 deletions
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c
index 686f5a4263..afebd0c71c 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c
@@ -1,4 +1,6 @@
/*
+ * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org>
+ *
* Copyright (c) 2011 Sebastian Huber. All rights reserved.
*
* embedded brains GmbH
@@ -24,5 +26,9 @@ void bsp_reset(void)
rtems_interrupt_disable(level);
- _ARMV7M_NVIC->reserved_5 [0] = 0;
+ _ARMV7M_SCB->aircr = ARMV7M_SCB_AIRCR_VECTKEY
+ | ARMV7M_SCB_AIRCR_SYSRESETREQ;
+
+ while (true)
+ /* Do nothing */;
}
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
index a8b54f209c..23a04a5edc 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
@@ -1,11 +1,5 @@
/*
- * Copyright (c) 2011 Sebastian Huber. All rights reserved.
- *
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
+ * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -13,12 +7,99 @@
*/
#include <bsp.h>
-#include <bsp/bootcard.h>
+#include <bspopts.h>
#include <bsp/irq-generic.h>
-#include <bsp/irq.h>
-#include <bsp/linker-symbols.h>
+#include <bsp/lm3s69xx.h>
+#include <bsp/io.h>
+#include <bsp/syscon.h>
+#include <assert.h>
+
+static void init_main_osc(void)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+
+ uint32_t sysdiv_val = LM3S69XX_PLL_FREQUENCY / LM3S69XX_SYSTEM_CLOCK;
+ assert(sysdiv_val * LM3S69XX_SYSTEM_CLOCK == LM3S69XX_PLL_FREQUENCY);
+ assert((sysdiv_val >= 4) && (sysdiv_val <= 16));
+
+ uint32_t rcc = syscon->rcc;
+
+ rcc = (rcc & ~SYSCONRCC_USESYSDIV) | SYSCONRCC_BYPASS;
+ syscon->rcc = rcc;
+
+ rcc = (rcc & ~(SYSCONRCC_PWRDN | SYSCONRCC_XTAL_MSK | SYSCONRCC_OSCSRC_MSK))
+ | SYSCONRCC_XTAL(LM3S69XX_XTAL_CONFIG) | SYSCONRCC_OSCSRC_MOSC;
+ syscon->rcc = rcc;
+
+ rcc = (rcc & ~SYSCONRCC_SYSDIV_MSK) | SYSCONRCC_SYSDIV(sysdiv_val / 2 - 1)
+ | SYSCONRCC_USESYSDIV;
+ syscon->rcc = rcc;
+
+ while ((syscon->ris & SYSCONRIS_PLLLRIS) == 0)
+ /* Wait for PLL lock */;
+
+ rcc &= ~SYSCONRCC_BYPASS;
+ syscon->rcc = rcc;
+}
+
+static const lm3s69xx_gpio_config start_config_gpio[] = {
+#ifdef LM3S69XX_ENABLE_UART_0
+#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965)
+ LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_A, 0),
+ LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_A, 1),
+#else
+#error No GPIO pin configuration for UART 0
+#endif
+#endif /* LM3S69XX_ENABLE_UART_0 */
+
+#ifdef LM3S69XX_ENABLE_UART_1
+#if defined(LM3S69XX_MCU_LM3S3749)
+ LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_B, 0),
+ LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_B, 1),
+#elif defined(LM3S69XX_MCU_LM3S6965)
+ LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_D, 2);
+ LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_D, 3);
+#else
+#error No GPIO pin configuration for UART 1
+#endif
+#endif /* LM3S69XX_ENABLE_UART_1 */
+
+#ifdef LM3S69XX_ENABLE_UART_2
+#if defined(LM3S69XX_MCU_LM3S3749)
+ LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_D, 0),
+ LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_D, 1),
+#elif defined(LM3S69XX_MCU_LM3S6965)
+ LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_G, 0),
+ LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_G, 1),
+#else
+#error No GPIO pin configuration for UART 2
+#endif
+#endif /* LM3S69XX_ENABLE_UART_2 */
+};
+
+static void init_gpio(void)
+{
+#if LM3S69XX_USE_AHB_FOR_GPIO
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+
+ syscon->gpiohbctl |= SYSCONGPIOHBCTL_PORTA | SYSCONGPIOHBCTL_PORTB
+ | SYSCONGPIOHBCTL_PORTC | SYSCONGPIOHBCTL_PORTD
+ | SYSCONGPIOHBCTL_PORTE | SYSCONGPIOHBCTL_PORTF
+ | SYSCONGPIOHBCTL_PORTG
+#if LM3S69XX_NUM_GPIO_BLOCKS > 7
+ | SYSCONGPIOHBCTL_PORTH
+#endif
+ ;
+
+#endif /* LM3S69XX_USE_AHB_FOR_GPIO */
+
+ lm3s69xx_gpio_set_config_array(start_config_gpio,
+ sizeof(start_config_gpio) / sizeof(start_config_gpio[0]));
+}
void bsp_start(void)
{
+ init_main_osc();
+ init_gpio();
bsp_interrupt_initialize();
}
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/io.c b/c/src/lib/libbsp/arm/lm3s69xx/startup/io.c
new file mode 100644
index 0000000000..a84dbf508a
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/io.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp/io.h>
+#include <bsp/lm3s69xx.h>
+#include <bsp/syscon.h>
+#include <rtems.h>
+
+static void set_bit(volatile uint32_t *reg, unsigned index, uint32_t set)
+{
+ uint32_t mask = 1U;
+ uint32_t val = *reg;
+
+ val &= ~(mask << index);
+ val |= set << index;
+
+ *reg = val;
+}
+
+static void set_config(unsigned int pin, const lm3s69xx_gpio_config *config)
+{
+ unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin);
+ volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port);
+ unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ lm3s69xx_syscon_enable_gpio_clock(port, true);
+
+ /* Disable digital and analog functions before reconfiguration. */
+ set_bit(&gpio->den, index, 0);
+ set_bit(&gpio->amsel, index, 0);
+
+ set_bit(&gpio->afsel, index, config->alternate);
+ set_bit(&gpio->dir, index, config->dir);
+ set_bit(&gpio->odr, index, config->otype);
+
+ switch (config->drive) {
+ case LM3S69XX_GPIO_DRIVE_4MA:
+ gpio->dr4r |= 1 << index;
+ break;
+ case LM3S69XX_GPIO_DRIVE_8MA:
+ gpio->dr8r |= 1 << index;
+ break;
+ default:
+ gpio->dr2r |= 1 << index;
+ break;
+ }
+
+ switch (config->pull) {
+ case LM3S69XX_GPIO_PULL_UP:
+ gpio->pur |= 1 << index;
+ break;
+ case LM3S69XX_GPIO_PULL_DOWN:
+ gpio->pdr |= 1 << index;
+ break;
+ default:
+ set_bit(&gpio->pdr, index, 0);
+ set_bit(&gpio->pur, index, 0);
+ break;
+ }
+
+ set_bit(&gpio->slr, index, config->slr);
+
+ set_bit(&gpio->den, index, config->digital);
+ set_bit(&gpio->amsel, index, config->analog);
+
+ rtems_interrupt_enable(level);
+}
+
+void lm3s69xx_gpio_set_config(const lm3s69xx_gpio_config *config)
+{
+ unsigned int current = config->pin_first;
+ unsigned int last = config->pin_last;
+
+ while (current <= last) {
+ set_config(current, config);
+ current++;
+ }
+}
+
+void lm3s69xx_gpio_set_config_array(const lm3s69xx_gpio_config *configs, unsigned int count)
+{
+ unsigned int i;
+
+ for (i = 0; i < count; i++)
+ lm3s69xx_gpio_set_config(&configs[i]);
+}
+
+/**
+ * Enables/disables digital function on the specified pin.
+ */
+void lm3s69xx_gpio_digital_enable(unsigned int pin, bool enable)
+{
+ unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin);
+ volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port);
+ unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ set_bit(&gpio->den, index, enable);
+ rtems_interrupt_enable(level);
+}
+
+/**
+ * Enables/disables analog mode on the specified pin.
+ */
+void lm3s69xx_gpio_analog_mode_select(unsigned int pin, bool enable)
+{
+ unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin);
+ volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port);
+ unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ set_bit(&gpio->amsel, index, enable);
+ rtems_interrupt_enable(level);
+}
+
+void lm3s69xx_gpio_set_pin(unsigned int pin, bool set)
+{
+ unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin);
+ volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port);
+ unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin);
+ uint32_t mask = 1U << index;
+
+ gpio->data[mask] = set ? mask : 0;
+}
+
+bool lm3s69xx_gpio_get_pin(unsigned int pin)
+{
+ unsigned int port = LM3S69XX_GPIO_PORT_OF_PIN(pin);
+ volatile lm3s69xx_gpio *gpio = LM3S69XX_GPIO(port);
+ unsigned int index = LM3S69XX_GPIO_INDEX_OF_PIN(pin);
+ uint32_t mask = 1U << index;
+
+ return gpio->data[mask] != 0;
+}
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s3749 b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s3749
new file mode 100644
index 0000000000..acfddc72e2
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s3749
@@ -0,0 +1,28 @@
+/**
+ * @file
+ *
+ * @brief Memory map.
+ */
+
+MEMORY {
+ RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 64K
+ ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 128K
+}
+
+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);
+
+INCLUDE linkcmds.armv7m
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965 b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965
index 72c06a8c7c..573c9ffa5a 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965
@@ -5,8 +5,8 @@
*/
MEMORY {
- RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 16M
- ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 64M
+ RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 64K
+ ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 256K
}
REGION_ALIAS ("REGION_START", ROM_INT);
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu
new file mode 100644
index 0000000000..72c06a8c7c
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu
@@ -0,0 +1,28 @@
+/**
+ * @file
+ *
+ * @brief Memory map.
+ */
+
+MEMORY {
+ RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 16M
+ ROM_INT (RX) : ORIGIN = 0x00000000, LENGTH = 64M
+}
+
+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);
+
+INCLUDE linkcmds.armv7m
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c b/c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c
new file mode 100644
index 0000000000..463bfd7d51
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+
+#include <bsp/syscon.h>
+#include <bsp/lm3s69xx.h>
+#include <rtems.h>
+
+static void delay_3_clocks(void)
+{
+ asm volatile(
+ "nop\n\t"
+ "nop\n\t"
+ "nop");
+}
+
+void lm3s69xx_syscon_enable_gpio_clock(unsigned int port, bool enable)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+ uint32_t mask = 1 << port;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ if (enable)
+ syscon->rcgc2 |= mask;
+ else
+ syscon->rcgc2 &= ~mask;
+
+ delay_3_clocks();
+
+ rtems_interrupt_enable(level);
+}
+
+void lm3s69xx_syscon_enable_uart_clock(unsigned int port, bool enable)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+ uint32_t mask = 1 << port;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ if (enable)
+ syscon->rcgc1 |= mask;
+ else
+ syscon->rcgc1 &= ~mask;
+
+ delay_3_clocks();
+
+ rtems_interrupt_enable(level);
+}
+
+void lm3s69xx_syscon_enable_ssi_clock(unsigned int port, bool enable)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+ uint32_t mask = 1 << (port + 4);
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ if (enable)
+ syscon->rcgc1 |= mask;
+ else
+ syscon->rcgc1 &= ~mask;
+
+ delay_3_clocks();
+
+ rtems_interrupt_enable(level);
+}
+
+void lm3s69xx_syscon_enable_pwm_clock(bool enable)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+
+ if (enable)
+ syscon->rcgc0 |= SYSCONRCGC0_PWM;
+ else
+ syscon->rcgc0 &= ~SYSCONRCGC0_PWM;
+
+ delay_3_clocks();
+
+ rtems_interrupt_enable(level);
+}
+
+/**
+ * Sets PWMDIV field in the RCC register.
+ *
+ * @note div should be one of SCRCC_PWMDIV_DIV?_VAL constants.
+ */
+void lm3s69xx_syscon_set_pwmdiv(unsigned int div)
+{
+ volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable(level);
+ syscon->rcc = (syscon->rcc & ~SYSCONRCC_PWMDIV_MSK) | SYSCONRCC_PWMDIV(div)
+ | SYSCONRCC_USEPWMDIV;
+ rtems_interrupt_enable(level);
+}