From f22bba3cb43182374bbddfad4e28545f89bd14ed Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Fri, 26 Apr 2013 11:03:59 +0200 Subject: bsp/lm3s69xx: New BSP variants Add support for LM3S3749. --- c/src/lib/libbsp/arm/lm3s69xx/startup/bspreset.c | 8 +- c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c | 101 +++++++++++++-- c/src/lib/libbsp/arm/lm3s69xx/startup/io.c | 144 +++++++++++++++++++++ .../libbsp/arm/lm3s69xx/startup/linkcmds.lm3s3749 | 28 ++++ .../libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965 | 4 +- .../arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu | 28 ++++ c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c | 106 +++++++++++++++ 7 files changed, 406 insertions(+), 13 deletions(-) create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/startup/io.c create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s3749 create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm3s6965_qemu create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c (limited to 'c/src/lib/libbsp/arm/lm3s69xx/startup') 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 + * * 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 - * + * Copyright © 2013 Eugeniy Meshcheryakov * * 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 -#include +#include #include -#include -#include +#include +#include +#include +#include + +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 + * + * 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 +#include +#include +#include + +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 + * + * 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 +#include +#include + +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); +} -- cgit v1.2.3