[add, wip] example/lcd
authorFabien Le Mentec <texane@gmail.com>
Sun, 16 Oct 2011 11:01:11 +0000 (06:01 -0500)
committerFabien Le Mentec <texane@gmail.com>
Sun, 16 Oct 2011 11:01:11 +0000 (06:01 -0500)
example/lcd/Makefile [new file with mode: 0644]
example/lcd/linker_stm32l.lds [new file with mode: 0644]
example/lcd/main.c [new file with mode: 0644]

diff --git a/example/lcd/Makefile b/example/lcd/Makefile
new file mode 100644 (file)
index 0000000..eeb4813
--- /dev/null
@@ -0,0 +1,28 @@
+EXECUTABLE=lcd.elf
+BIN_IMAGE=lcd.bin
+
+CC=arm-none-eabi-gcc
+OBJCOPY=arm-none-eabi-objcopy
+
+CFLAGS=-O2 -mlittle-endian -mthumb
+CFLAGS+=-mcpu=cortex-m3 -ffreestanding -nostdlib -nostdinc
+
+# to run from SRAM
+CFLAGS+=-Wl,-T,linker_stm32l.lds
+
+# to write to flash then run
+# CFLAGS+=-Wl,-Ttext,0x08000000 -Wl,-e,0x08000000
+
+all: $(BIN_IMAGE)
+
+$(BIN_IMAGE): $(EXECUTABLE)
+       $(OBJCOPY) -O binary $^ $@
+
+$(EXECUTABLE): main.c
+       $(CC) $(CFLAGS) $^ -o $@
+
+clean:
+       rm -rf $(EXECUTABLE)
+       rm -rf $(BIN_IMAGE)
+
+.PHONY: all clean
diff --git a/example/lcd/linker_stm32l.lds b/example/lcd/linker_stm32l.lds
new file mode 100644 (file)
index 0000000..58b894f
--- /dev/null
@@ -0,0 +1,54 @@
+OUTPUT_FORMAT("elf32-littlearm")
+ENTRY(_main)
+
+MEMORY
+{
+       sram : ORIGIN = 0x20000000, LENGTH = 0x4000
+}
+
+SECTIONS
+{
+       .text(ORIGIN(sram)):
+       {
+               _main = .;
+               _ftext = .;
+               *(.text .stub .text.* .gnu.linkonce.t.*)
+               _etext = .;
+       } > sram
+
+       .rodata :
+       {
+               . = ALIGN(4);
+               _frodata = .;
+               *(.rodata .rodata.* .gnu.linkonce.r.*)
+               *(.rodata1)
+               _erodata = .;
+       } > sram
+
+       .data :
+       {
+               . = ALIGN(4);
+               _fdata = .;
+               *(.data .data.* .gnu.linkonce.d.*)
+               *(.data1)
+               _gp = ALIGN(16);
+               *(.sdata .sdata.* .gnu.linkonce.s.*)
+               _edata = .;
+       } > sram
+
+       .bss :
+       {
+               . = ALIGN(4);
+               _fbss = .;
+               *(.dynsbss)
+               *(.sbss .sbss.* .gnu.linkonce.sb.*)
+               *(.scommon)
+               *(.dynbss)
+               *(.bss .bss.* .gnu.linkonce.b.*)
+               *(COMMON)
+               _ebss = .;
+               _end = .;
+       } > sram
+}
+
+PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4);
diff --git a/example/lcd/main.c b/example/lcd/main.c
new file mode 100644 (file)
index 0000000..b693084
--- /dev/null
@@ -0,0 +1,336 @@
+/* this example is only for stm32l discover */
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+
+
+/* boot mode */
+
+#define CONFIG_BOOT_SRAM 1
+#define CONFIG_BOOT_FLASH 0
+
+
+/* gpios
+   refer to CD00277537.pdf, APB memory space.
+   refer to CD00240193.pdf, GPIO.
+*/
+
+#define GPIOA 0x40020000
+#define GPIOA_MODER (GPIOA + 0x00)
+#define GPIOA_ODR (GPIOA + 0x14)
+
+#define GPIOB 0x40020400
+#define GPIOB_MODER (GPIOB + 0x00)
+#define GPIOB_ODR (GPIOB + 0x14)
+
+#define GPIOC 0x40020800
+#define GPIOC_MODER (GPIOC + 0x00)
+#define GPIOC_ODR (GPIOC + 0x14)
+
+
+/* leds */
+
+#define LED_BLUE (1 << 6) /* port B, pin 6 */
+#define LED_GREEN (1 << 7) /* port B, pin 7 */
+
+static inline void setup_leds(void)
+{
+  /* configure port 6 and 7 as output */
+  *(volatile uint32_t*)GPIOB_MODER |= (1 << (7 * 2)) | (1 << (6 * 2));
+}
+
+static inline void switch_leds_on(void)
+{
+  *(volatile uint32_t*)GPIOB_ODR = LED_BLUE | LED_GREEN;
+}
+
+static inline void switch_leds_off(void)
+{
+  *(volatile uint32_t*)GPIOB_ODR = 0;
+}
+
+
+/* lcd. refer to DM00027954.pdf. */
+
+#if 0
+
+#define LCD_SEG0 PA1
+#define LCD_SEG1 PA2
+#define LCD_SEG2 PA3
+#define LCD_SEG3 PB3
+#define LCD_SEG4 PB4
+#define LCD_SEG5 PB5
+#define LCD_SEG6 PB10
+#define LCD_SEG7 PB11
+#define LCD_SEG8 PB12
+#define LCD_SEG9 PB13
+#define LCD_SEG10 PB14
+#define LCD_SEG11 PB15
+#define LCD_SEG12 PA15
+#define LCD_SEG13 PB8
+#define LCD_SEG14 PC0
+#define LCD_SEG15 PC1
+#define LCD_SEG16 PC2
+#define LCD_SEG17 PC3
+#define LCD_SEG18 PC6
+#define LCD_SEG19 PC7
+#define LCD_SEG20 PC8
+#define LCD_SEG21 PC9
+#define LCD_SEG22 PC10
+#define LCD_SEG23 PC11
+#define LCD_COM0 PA8
+#define LCD_COM1 PA9
+#define LCD_COM2 PA10
+#define LCD_COM3 PB9
+
+#endif
+
+static void setup_lcd(void)
+{
+  /* set every port in digital output mode  */
+
+  /* PA[1:3,8:10,15] */
+  *(volatile uint32_t*)GPIOA_MODER |=
+    (1 << (1 * 2)) |
+    (1 << (2 * 2)) |
+    (1 << (3 * 2)) |
+    (1 << (8 * 2)) |
+    (1 << (9 * 2)) |
+    (1 << (10 * 2)) |
+    (1 << (15 * 2));
+
+  /* PB[3:5,8:15] */
+  *(volatile uint32_t*)GPIOB_MODER |=
+    (1 << (3 * 2)) |
+    (1 << (4 * 2)) |
+    (1 << (5 * 2)) |
+    (1 << (8 * 2)) |
+    (1 << (9 * 2)) |
+    (1 << (10 * 2)) |
+    (1 << (11 * 2)) |
+    (1 << (12 * 2)) |
+    (1 << (13 * 2)) |
+    (1 << (14 * 2)) |
+    (1 << (15 * 2));
+
+  /* PC[0:3,6:11] */
+  *(volatile uint32_t*)GPIOC_MODER |=
+    (1 << (0 * 2)) |
+    (1 << (1 * 2)) |
+    (1 << (2 * 2)) |
+    (1 << (3 * 2)) |
+    (1 << (6 * 2)) |
+    (1 << (7 * 2)) |
+    (1 << (8 * 2)) |
+    (1 << (9 * 2)) |
+    (1 << (10 * 2)) |
+    (1 << (11 * 2));
+}
+
+static inline void set_lcd_com(unsigned int i, unsigned int val)
+{
+  /* table for LCD_COM<N> */
+  static const uint32_t regs[4] = { GPIOA_ODR, GPIOA_ODR, GPIOA_ODR, GPIOB_ODR };
+  static const uint8_t bits[4] = { 8, 9, 10, 9 };
+
+  uint32_t tmp = *(volatile uint32_t*)regs[i];
+  tmp &= ~(1 << bits[i]);
+  tmp |= val << bits[i];
+  *(volatile uint32_t*)regs[i] = tmp;
+}
+
+static void clear_lcd(void)
+{
+  /* tables for LCD_SEG<N> */
+
+  static const uint32_t regs[24] =
+  {
+    GPIOA_ODR,
+    GPIOA_ODR,
+    GPIOA_ODR,
+
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+    GPIOB_ODR,
+
+    GPIOA_ODR,
+
+    GPIOB_ODR,
+
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR,
+    GPIOC_ODR
+  };
+
+  static const uint8_t bits[24] =
+  {
+    1,
+    2,
+    3,
+
+    3,
+    4,
+    5,
+    10,
+    11,
+    12,
+    13,
+    14,
+    15,
+
+    15,
+
+    8,
+
+    0,
+    1,
+    2,
+    3,
+    6,
+    7,
+    8,
+    9,
+    10,
+    11
+  };
+
+  /* foreach lcd selector, select and zero */
+  unsigned int i;
+  for (i = 0; i < sizeof(regs) / sizeof(regs[0]); ++i)
+  {
+    /* select */
+    *(volatile uint32_t*)regs[i] |= 1 << bits[i];
+
+    /* set segments */
+    set_lcd_com(0, 0);
+    set_lcd_com(1, 0);
+    set_lcd_com(2, 0);
+    set_lcd_com(3, 0);
+
+    /* deselect */
+    *(volatile uint32_t*)regs[i] &= ~(1 << bits[i]);
+  }
+}
+
+static void update_lcd(void)
+{
+  static unsigned int state = 0;
+
+  clear_lcd();
+
+/*   if (state == 0) */
+  if (1)
+  {
+    /* left square (segments: 1A, 1B, 1C, 1D, 1E, 1F) */
+
+    /* 1A, 1B: PC10, COM0, COM1 */
+    *(volatile uint32_t*)GPIOC_ODR |= 1 << 10;
+    set_lcd_com(0, 1);
+    set_lcd_com(1, 1);
+    set_lcd_com(2, 0);
+    set_lcd_com(3, 0);
+    *(volatile uint32_t*)GPIOC_ODR &= ~(1 << 10);
+
+    /* 1C: PA2, COM1 */
+    *(volatile uint32_t*)GPIOA_ODR |= 1 << 2;
+    set_lcd_com(0, 0);
+    set_lcd_com(1, 1);
+    set_lcd_com(2, 0);
+    set_lcd_com(3, 0);
+    *(volatile uint32_t*)GPIOA_ODR &= ~(1 << 2);
+
+    /* 1D, 1E: PA1, COM0, COM1 */
+    *(volatile uint32_t*)GPIOA_ODR |= 1 << 1;
+    set_lcd_com(0, 1);
+    set_lcd_com(1, 1);
+    set_lcd_com(2, 0);
+    set_lcd_com(3, 0);
+    *(volatile uint32_t*)GPIOA_ODR &= ~(1 << 1);
+
+    /* 1F: PC11, COM1 */
+    *(volatile uint32_t*)GPIOC_ODR |= 1 << 11;
+    set_lcd_com(0, 0);
+    set_lcd_com(1, 1);
+    set_lcd_com(2, 0);
+    set_lcd_com(3, 0);
+    *(volatile uint32_t*)GPIOC_ODR &= ~(1 << 11);
+  }
+  else
+  {
+    /* right square (segments: 6A, 6B, 6C, 6D, 6E, 6F) */
+  }
+
+/*   state ^= 1; */
+}
+
+
+#define delay()                                                \
+do {                                                   \
+  register unsigned int i;                             \
+  for (i = 0; i < 1000000; ++i)                                \
+    __asm__ __volatile__ ("nop\n\t":::"memory");       \
+} while (0)
+
+
+#if CONFIG_BOOT_SRAM
+
+extern uint32_t _fstack;
+
+static inline void setup_stack(void)
+{
+  /* setup the stack to point to _fstack (refer to ld script) */
+
+  static const uint32_t fstack = (uint32_t)&_fstack;
+
+  __asm__ __volatile__
+    (
+     "ldr sp, %0\n\t"
+     : 
+     : "m"(fstack)
+     : "sp"
+    );
+}
+
+#endif /* CONFIG_BOOT_SRAM */
+
+
+static void __attribute__((naked)) __attribute__((used)) main(void)
+{
+#if CONFIG_BOOT_SRAM
+  /* do not use previsouly setup stack, if any */
+  setup_stack();
+#endif /* CONFIG_BOOT_SRAM */
+
+  setup_leds();
+
+  setup_lcd();
+  clear_lcd();
+/*   while (1) ; */
+
+  update_lcd();
+  while (1) ;
+
+  while (1)
+  {
+    /* update_lcd(); */
+    switch_leds_on();
+    delay();
+
+    /* update_lcd(); */
+    switch_leds_off();
+    delay();
+  }
+}