[PATCH] bsp/lm4f120: new BSP to support TI LM4F120 XL LaunchPad board

Karel Gardas karel.gardas at centrum.cz
Thu Aug 29 20:20:03 UTC 2013


---
 c/src/lib/libbsp/arm/lm3s69xx/configure.ac         |   11 +++-
 c/src/lib/libbsp/arm/lm3s69xx/include/lm3s69xx.h   |   15 +++++-
 c/src/lib/libbsp/arm/lm3s69xx/include/syscon.h     |    1 +
 .../libbsp/arm/lm3s69xx/make/custom/lm4f120.cfg    |    5 ++
 c/src/lib/libbsp/arm/lm3s69xx/ssi/ssi.c            |    4 +-
 c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c   |   59 +++++++++++++++++--
 .../libbsp/arm/lm3s69xx/startup/linkcmds.lm4f120   |   28 +++++++++
 c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c     |    9 +++
 8 files changed, 121 insertions(+), 11 deletions(-)
 create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/make/custom/lm4f120.cfg
 create mode 100644 c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm4f120

diff --git a/c/src/lib/libbsp/arm/lm3s69xx/configure.ac b/c/src/lib/libbsp/arm/lm3s69xx/configure.ac
index 833c56d..c9d40cf 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/configure.ac
+++ b/c/src/lib/libbsp/arm/lm3s69xx/configure.ac
@@ -25,11 +25,13 @@ RTEMS_BSPOPTS_SET([BSP_SMALL_MEMORY],[*_qemu],[])
 RTEMS_BSPOPTS_SET([BSP_SMALL_MEMORY],[*],[1])
 RTEMS_BSPOPTS_HELP([BSP_SMALL_MEMORY],[disable testsuite samples with high memory demands])
 
-RTEMS_BSPOPTS_SET([LM3S69XX_SYSTEM_CLOCK],[*],[50000000U])
+RTEMS_BSPOPTS_SET([LM3S69XX_SYSTEM_CLOCK],[lm3s*],[50000000U])
+RTEMS_BSPOPTS_SET([LM3S69XX_SYSTEM_CLOCK],[lm4f*],[80000000U])
 RTEMS_BSPOPTS_HELP([LM3S69XX_SYSTEM_CLOCK],[system clock in Hz])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_XTAL_CONFIG],[lm3s6965*],[0xE]) dnl 8MHz XTAL
 RTEMS_BSPOPTS_SET([LM3S69XX_XTAL_CONFIG],[lm3s3749*],[0x10]) dnl 10MHz XTAL
+RTEMS_BSPOPTS_SET([LM3S69XX_XTAL_CONFIG],[lm4f120*],[0x15]) dnl 16MHz XTAL
 RTEMS_BSPOPTS_HELP([LM3S69XX_XTAL_CONFIG],[crystal configuration for RCC register])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_SSI_CLOCK],[*],[1000000U])
@@ -49,17 +51,21 @@ RTEMS_BSPOPTS_HELP([LM3S69XX_ENABLE_UART_2],[enable UART 2])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_NUM_GPIO_BLOCKS],[lm3s3749*],[8])
 RTEMS_BSPOPTS_SET([LM3S69XX_NUM_GPIO_BLOCKS],[lm3s6965*],[7])
+RTEMS_BSPOPTS_SET([LM3S69XX_NUM_GPIO_BLOCKS],[lm4f120*],[6])
 RTEMS_BSPOPTS_HELP([LM3S69XX_NUM_GPIO_BLOCKS],[number of GPIO blocks supported by MCU])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_NUM_SSI_BLOCKS],[lm3s3749*],[2])
 RTEMS_BSPOPTS_SET([LM3S69XX_NUM_SSI_BLOCKS],[lm3s6965*],[1])
+RTEMS_BSPOPTS_SET([LM3S69XX_NUM_SSI_BLOCKS],[lm4f120*],[4])
 RTEMS_BSPOPTS_HELP([LM3S69XX_NUM_SSI_BLOCKS],[number of SSI blocks supported by MCU])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_HAS_UDMA],[lm3s3749*],[1])
+RTEMS_BSPOPTS_SET([LM3S69XX_HAS_UDMA],[lm4f*],[1])
 RTEMS_BSPOPTS_SET([LM3S69XX_HAS_UDMA],[*],[0])
 RTEMS_BSPOPTS_HELP([LM3S69XX_HAS_UDMA],[defined if MCU supports UDMA])
 
 RTEMS_BSPOPTS_SET([LM3S69XX_USE_AHB_FOR_GPIO],[lm3s3749*],[1])
+RTEMS_BSPOPTS_SET([LM3S69XX_USE_AHB_FOR_GPIO],[lm4f*],[1])
 RTEMS_BSPOPTS_SET([LM3S69XX_USE_AHB_FOR_GPIO],[*],[0])
 RTEMS_BSPOPTS_HELP([LM3S69XX_USE_AHB_FOR_GPIO],[use AHB apperture to access GPIO registers])
 
@@ -69,6 +75,9 @@ RTEMS_BSPOPTS_HELP([LM3S69XX_MCU_LM3S3749],[board has LM3S3749 MCU])
 RTEMS_BSPOPTS_SET([LM3S69XX_MCU_LM3S6965],[lm3s6965*],[1])
 RTEMS_BSPOPTS_HELP([LM3S69XX_MCU_LM3S6965],[board has LM3S6965 MCU])
 
+RTEMS_BSPOPTS_SET([LM3S69XX_MCU_LM4F120],[lm4f120*],[1])
+RTEMS_BSPOPTS_HELP([LM3S69XX_MCU_LM4F120],[board has LM4F120xxx MCU])
+
 RTEMS_BSP_CLEANUP_OPTIONS(0, 0)
 RTEMS_BSP_LINKCMDS
 
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/include/lm3s69xx.h b/c/src/lib/libbsp/arm/lm3s69xx/include/lm3s69xx.h
index 7402624..2b38d93 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/include/lm3s69xx.h
+++ b/c/src/lib/libbsp/arm/lm3s69xx/include/lm3s69xx.h
@@ -32,10 +32,12 @@
 #define LM3S69XX_GPIO_D_BASE 0x4005b000
 #define LM3S69XX_GPIO_E_BASE 0x4005c000
 #define LM3S69XX_GPIO_F_BASE 0x4005d000
+#if LM3S69XX_NUM_GPIO_BLOCKS > 6
 #define LM3S69XX_GPIO_G_BASE 0x4005e000
 #if LM3S69XX_NUM_GPIO_BLOCKS > 7
 #define LM3S69XX_GPIO_H_BASE 0x4005f000
 #endif
+#endif
 
 #define LM3S69XX_GPIO(port) ((volatile lm3s69xx_gpio *)(LM3S69XX_GPIO_A_BASE + (port) * 0x1000))
 #else /* LM3S69XX_USE_AHB_FOR_GPIO */
@@ -45,10 +47,12 @@
 #define LM3S69XX_GPIO_D_BASE 0x40007000
 #define LM3S69XX_GPIO_E_BASE 0x40024000
 #define LM3S69XX_GPIO_F_BASE 0x40025000
+#if LM3S69XX_NUM_GPIO_BLOCKS > 6
 #define LM3S69XX_GPIO_G_BASE 0x40026000
 #if LM3S69XX_NUM_GPIO_BLOCKS > 7
 #define LM3S69XX_GPIO_H_BASE 0x40027000
 #endif
+#endif
 
 #define LM3S69XX_GPIO(port) ((volatile lm3s69xx_gpio *)(((port) < 4) ? \
            (LM3S69XX_GPIO_A_BASE + (port) * 0x1000) : \
@@ -58,6 +62,12 @@
 #define LM3S69XX_SSI_0_BASE 0x40008000
 #if LM3S69XX_NUM_SSI_BLOCKS > 1
 #define LM3S69XX_SSI_1_BASE 0x40009000
+#if LM3S69XX_NUM_SSI_BLOCKS > 2
+#define LM3S69XX_SSI_2_BASE 0x4000A000
+#if LM3S69XX_NUM_SSI_BLOCKS > 3
+#define LM3S69XX_SSI_3_BASE 0x4000B000
+#endif
+#endif
 #endif
 
 #define LM3S69XX_SYSCON ((volatile lm3s69xx_syscon *)LM3S69XX_SYSCON_BASE)
@@ -194,8 +204,11 @@ typedef struct {
   uint32_t gpiohbctl;
 
 #define SYSCONRCC2_USERCC2 BSP_BIT32(31)
+#define SYSCONRCC2_DIV400 BSP_BIT32(30)
 #define SYSCONRCC2_SYSDIV2(val) BSP_FLD32(val, 23, 28)
-#define SYSCONRCC2_SYSDIV2_MSK(val) BSP_MSK32(23, 28)
+#define SYSCONRCC2_SYSDIV2_MSK BSP_MSK32(23, 28)
+#define SYSCONRCC2_SYSDIV2EXT(val) BSP_FLD32(val, 22, 28)
+#define SYSCONRCC2_SYSDIV2EXT_MSK BSP_MSK32(22, 28)
 #define SYSCONRCC2_USBPWRDN BSP_BIT32(14)
 #define SYSCONRCC2_PWRDN2 BSP_BIT32(13)
 #define SYSCONRCC2_BYPASS2 BSP_BIT32(11)
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/include/syscon.h b/c/src/lib/libbsp/arm/lm3s69xx/include/syscon.h
index 0f3dc3b..78af4a7 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/include/syscon.h
+++ b/c/src/lib/libbsp/arm/lm3s69xx/include/syscon.h
@@ -18,6 +18,7 @@ void lm3s69xx_syscon_enable_uart_clock(unsigned int port, bool enable);
 void lm3s69xx_syscon_enable_ssi_clock(unsigned int port, bool enable);
 void lm3s69xx_syscon_enable_pwm_clock(bool enable);
 void lm3s69xx_syscon_set_pwmdiv(unsigned int div);
+void lm3s69xx_syscon_delay_3x_clocks(unsigned long x_count);
 
 #ifdef __cplusplus
 }
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/make/custom/lm4f120.cfg b/c/src/lib/libbsp/arm/lm3s69xx/make/custom/lm4f120.cfg
new file mode 100644
index 0000000..aa7961e
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/make/custom/lm4f120.cfg
@@ -0,0 +1,5 @@
+#
+#  Config file for LM4F120XL.
+#
+
+include $(RTEMS_ROOT)/make/custom/lm3s69xx.inc
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/ssi/ssi.c b/c/src/lib/libbsp/arm/lm3s69xx/ssi/ssi.c
index d5f3d17..9e5b2b5 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/ssi/ssi.c
+++ b/c/src/lib/libbsp/arm/lm3s69xx/ssi/ssi.c
@@ -134,7 +134,7 @@ static lm3s69xx_ssi_bus_entry ssi_0_bus = {
   .bus_number = 0,
   .idle_char = 0xffff,
   .io_configs = {
-#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965)
+#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965) || defined(LM3S69XX_MCU_LM4F120)
     LM3S69XX_PIN_SSI_TX(LM3S69XX_PORT_A, 2), /* CLK */
     LM3S69XX_PIN_SSI_TX(LM3S69XX_PORT_A, 5), /* TX */
     LM3S69XX_PIN_SSI_RX(LM3S69XX_PORT_A, 4)  /* RX */
@@ -156,7 +156,7 @@ static lm3s69xx_ssi_bus_entry ssi_1_bus = {
   .bus_number = 1,
   .idle_char = 0xffff,
   .io_configs = {
-#if defined(LM3S69XX_MCU_LM3S3749)
+#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM4F120)
     LM3S69XX_PIN_SSI_TX(LM3S69XX_PORT_E, 0), /* CLK */
     LM3S69XX_PIN_SSI_TX(LM3S69XX_PORT_E, 3), /* TX */
     LM3S69XX_PIN_SSI_RX(LM3S69XX_PORT_E, 2)  /* RX */
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
index 442c713..a8329b6 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/bspstart.c
@@ -19,32 +19,70 @@ static void init_main_osc(void)
   volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
 
   uint32_t sysdiv_val = LM3S69XX_PLL_FREQUENCY / LM3S69XX_SYSTEM_CLOCK;
+#if defined(LM3S69XX_MCU_LM3S6965) || defined(LM3S69XX_MCU_LM3S3749)
   assert(sysdiv_val * LM3S69XX_SYSTEM_CLOCK == LM3S69XX_PLL_FREQUENCY);
+#endif
   assert((sysdiv_val >= 4) && (sysdiv_val <= 16));
 
   uint32_t rcc = syscon->rcc;
+  uint32_t rcc2 = syscon->rcc2;
 
   rcc = (rcc & ~SYSCONRCC_USESYSDIV) | SYSCONRCC_BYPASS;
+  rcc2 |= SYSCONRCC2_BYPASS2;
+
   syscon->rcc = rcc;
+  syscon->rcc2 = rcc2;
 
-  rcc = (rcc & ~(SYSCONRCC_PWRDN | SYSCONRCC_XTAL_MSK | SYSCONRCC_OSCSRC_MSK))
-      | SYSCONRCC_XTAL(LM3S69XX_XTAL_CONFIG) | SYSCONRCC_OSCSRC_MOSC;
+  /*
+   As per a note in Stellaris® LM4F120H5QR Microcontroller Data
+   Sheet on page 219: "When transitioning the system clock
+   configuration to use the MOSC as the fundamental clock source, the
+   MOSCDIS bit must be set prior to reselecting the MOSC or an
+   undefined system clock configuration can sporadically occur."
+  */
+
+  rcc |= SYSCONRCC_MOSCDIS;
   syscon->rcc = rcc;
 
-  rcc = (rcc & ~SYSCONRCC_SYSDIV_MSK) | SYSCONRCC_SYSDIV(sysdiv_val / 2 - 1)
-      | SYSCONRCC_USESYSDIV;
+  rcc = (rcc & ~(SYSCONRCC_XTAL_MSK))
+      | SYSCONRCC_XTAL(LM3S69XX_XTAL_CONFIG);
+  rcc2 = (rcc2 & ~(SYSCONRCC2_PWRDN2 | SYSCONRCC2_OSCSRC2_MSK))
+      | SYSCONRCC2_USERCC2 | SYSCONRCC2_OSCSRC2(0x0);
+
+  /* clear PLL lock interrupt */
+  syscon->misc &= (SYSCONMISC_PLLLMIS);
+
   syscon->rcc = rcc;
+  syscon->rcc2 = rcc2;
+  lm3s69xx_syscon_delay_3x_clocks(16);
+
+  /* since now, we'll use only RCC2 as SYSCONRCC2_USERCC2 and XTAL
+     (only available in RCC) are already set */
+
+  if (sysdiv_val % 2 == 0) {
+      rcc2 = (rcc2 & ~SYSCONRCC2_SYSDIV2_MSK) | SYSCONRCC2_SYSDIV2(sysdiv_val / 2 - 1);
+
+      rcc2 &= ~(SYSCONRCC2_DIV400);
+  }
+  else {
+      /* need to use DIV400 */
+      rcc2 = (rcc2 & ~SYSCONRCC2_SYSDIV2EXT_MSK) | SYSCONRCC2_SYSDIV2EXT(sysdiv_val - 1)
+          | SYSCONRCC2_DIV400;
+  }
+  syscon->rcc2 = rcc2;
 
   while ((syscon->ris & SYSCONRIS_PLLLRIS) == 0)
       /* Wait for PLL lock */;
 
-  rcc &= ~SYSCONRCC_BYPASS;
-  syscon->rcc = rcc;
+  rcc2 &= ~(SYSCONRCC2_BYPASS2);
+
+  syscon->rcc2 = rcc2;
+  lm3s69xx_syscon_delay_3x_clocks(16);
 }
 
 static const lm3s69xx_gpio_config start_config_gpio[] = {
 #ifdef LM3S69XX_ENABLE_UART_0
-#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965)
+#if defined(LM3S69XX_MCU_LM3S3749) || defined(LM3S69XX_MCU_LM3S6965) || defined(LM3S69XX_MCU_LM4F120)
   LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_A, 0),
   LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_A, 1),
 #else
@@ -59,6 +97,11 @@ static const lm3s69xx_gpio_config start_config_gpio[] = {
 #elif defined(LM3S69XX_MCU_LM3S6965)
   LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_D, 2),
   LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_D, 3),
+#elif defined(LM3S69XX_MCU_LM4F120)
+  LM3S69XX_PIN_UART_RX(LM3S69XX_PORT_B, 0),
+  LM3S69XX_PIN_UART_TX(LM3S69XX_PORT_B, 1),
+  LM3S69XX_PIN_UART_RTS(LM3S69XX_PORT_C, 4),
+  LM3S69XX_PIN_UART_CTS(LM3S69XX_PORT_C, 5),
 #else
 #error No GPIO pin configuration for UART 1
 #endif
@@ -85,10 +128,12 @@ static void init_gpio(void)
   syscon->gpiohbctl |= SYSCONGPIOHBCTL_PORTA | SYSCONGPIOHBCTL_PORTB
       | SYSCONGPIOHBCTL_PORTC | SYSCONGPIOHBCTL_PORTD
       | SYSCONGPIOHBCTL_PORTE | SYSCONGPIOHBCTL_PORTF
+#if LM3S69XX_NUM_GPIO_BLOCKS > 6
       | SYSCONGPIOHBCTL_PORTG
 #if LM3S69XX_NUM_GPIO_BLOCKS > 7
       | SYSCONGPIOHBCTL_PORTH
 #endif
+#endif
       ;
 
 #endif /* LM3S69XX_USE_AHB_FOR_GPIO */
diff --git a/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm4f120 b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm4f120
new file mode 100644
index 0000000..fe19ff3
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/linkcmds.lm4f120
@@ -0,0 +1,28 @@
+/**
+ * @file
+ *
+ * @brief Memory map.
+ */
+
+MEMORY {
+	RAM_INT (AIW) : ORIGIN = 0x20000000, LENGTH = 32K
+	ROM_INT (RX)  : 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);
+
+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
index 463bfd7..09b7a80 100644
--- a/c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c
+++ b/c/src/lib/libbsp/arm/lm3s69xx/startup/syscon.c
@@ -18,6 +18,15 @@ static void delay_3_clocks(void)
       "nop");
 }
 
+void __attribute__((naked)) lm3s69xx_syscon_delay_3x_clocks(unsigned long x_count)
+{
+    asm volatile(
+                 "subs  r0, #1\n\t"
+                 "bne   lm3s69xx_syscon_delay_3x_clocks\n\t"
+                 "bx    lr"
+                 );
+}
+
 void lm3s69xx_syscon_enable_gpio_clock(unsigned int port, bool enable)
 {
   volatile lm3s69xx_syscon *syscon = LM3S69XX_SYSCON;
-- 
1.7.3.2




More information about the devel mailing list