From: Fabien Le Mentec Date: Sun, 16 Oct 2011 11:01:11 +0000 (-0500) Subject: [add, wip] example/lcd X-Git-Url: https://git.gag.com/?p=fw%2Fstlink;a=commitdiff_plain;h=a255097c46cc5b9c41996dba85f023ccc9812ca6 [add, wip] example/lcd --- diff --git a/example/lcd/Makefile b/example/lcd/Makefile new file mode 100644 index 0000000..eeb4813 --- /dev/null +++ b/example/lcd/Makefile @@ -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 index 0000000..58b894f --- /dev/null +++ b/example/lcd/linker_stm32l.lds @@ -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 index 0000000..b693084 --- /dev/null +++ b/example/lcd/main.c @@ -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 */ + 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 */ + + 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(); + } +}