From 38f0e84d3b5da56c1441f2f779246ccf7b23d5c4 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Thu, 18 Feb 2021 23:01:57 +0100 Subject: add minimal LM4F120H5QR (LM4F120XL Stellaris Launchpad) support --- src/arch/lm4f120h5qr-stellaris/Makefile.inc | 130 ++++++++++++++++ src/arch/lm4f120h5qr-stellaris/arch.cc | 79 ++++++++++ src/arch/lm4f120h5qr-stellaris/driver/gpio.cc | 8 + src/arch/lm4f120h5qr-stellaris/driver/stdout.cc | 26 ++++ src/arch/lm4f120h5qr-stellaris/driver/uptime.cc | 8 + src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld | 11 ++ src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c | 177 ++++++++++++++++++++++ src/arch/lm4f120h5qr-stellaris/prompt | 1 + 8 files changed, 440 insertions(+) create mode 100644 src/arch/lm4f120h5qr-stellaris/Makefile.inc create mode 100644 src/arch/lm4f120h5qr-stellaris/arch.cc create mode 100644 src/arch/lm4f120h5qr-stellaris/driver/gpio.cc create mode 100644 src/arch/lm4f120h5qr-stellaris/driver/stdout.cc create mode 100644 src/arch/lm4f120h5qr-stellaris/driver/uptime.cc create mode 100644 src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld create mode 100644 src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c create mode 100644 src/arch/lm4f120h5qr-stellaris/prompt (limited to 'src') diff --git a/src/arch/lm4f120h5qr-stellaris/Makefile.inc b/src/arch/lm4f120h5qr-stellaris/Makefile.inc new file mode 100644 index 0000000..d49391b --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/Makefile.inc @@ -0,0 +1,130 @@ +# vim:ft=make +# +# Copyright 2021 Daniel Friesel +# +# SPDX-License-Identifier: BSD-2-Clause + +SERIAL_PORT ?= ttyACM0 + +cpu_freq ?= 80000000 + +INCLUDES += -Iext/libopencm3/include + +COMMON_FLAGS += --static -nostartfiles -g3 -Os -fno-common +COMMON_FLAGS += -ffunction-sections -fdata-sections +COMMON_FLAGS += -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DLM4F + +CC = arm-none-eabi-gcc +CXX = arm-none-eabi-g++ +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +SIZE = arm-none-eabi-size + +C_TARGETS += src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c +CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/arch.cc + +ifdef CONFIG_aspectc + CXX = ag++ -r build/repo.acp -v 0 --c_compiler arm-none-eabi-g++ -p . --Xcompiler +endif + +ifneq ($(findstring adc,${arch_drivers}), ) + CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/adc.cc +endif + +CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/gpio.cc +CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/stdout.cc + +# Commandline + +ifneq ($(findstring counter,${arch_drivers}), ) + CONFIG_arch_lm4f120h5qr_stellaris_driver_counter = y +endif + +#ifneq ($(findstring timer,${arch_drivers}), ) +# CONFIG_arch_lm4f120h5qr_stellaris_driver_timer = y +#endif + +ifeq (${timer_s}, 1) + CONFIG_arch_lm4f120h5qr_stellaris_driver_uptime = y +endif + +# Kconfig + +ifdef CONFIG_arch_lm4f120h5qr_stellaris_driver_counter + CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/counter.cc +endif + +#ifdef CONFIG_arch_lm4f120h5qr_stellaris_driver_timer +# CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/timer.cc +#endif + +ifdef CONFIG_arch_lm4f120h5qr_stellaris_driver_uptime + COMMON_FLAGS += -DTIMER_S + CXX_TARGETS += src/arch/lm4f120h5qr-stellaris/driver/uptime.cc +endif + + +ifneq (${cpu_freq}, ) + COMMON_FLAGS += -DF_CPU=${cpu_freq}UL +else + COMMON_FLAGS += -DF_CPU=80000000UL +endif + + +OBJECTS = ${CXX_TARGETS:.cc=.o} ${C_TARGETS:.c=.o} ${ASM_TARGETS:.S=.o} + +.cc.o: + ${QUIET}${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} -c -o $@ ${@:.o=.cc} + +.c.o: + ${QUIET}${CC} ${INCLUDES} ${COMMON_FLAGS} ${CFLAGS} -c -o $@ ${@:.o=.c} + +.S.o: + ${QUIET}${CC} ${INCLUDES} ${COMMON_FLAGS} -c -o $@ ${@:.o=.S} + +.s.o: + ${QUIET}${CC} ${INCLUDES} ${COMMON_FLAGS} -c -o $@ ${@:.o=.S} + +ext/libopencm3/Makefile: + git submodule update --init + +ext/libopencm3/lib/libopencm3_lm4f.a: ext/libopencm3/Makefile + ${MAKE} -C ext/libopencm3 + +build/system.elf: ${OBJECTS} ext/libopencm3/lib/libopencm3_stm32f4.a + ${QUIET}mkdir -p build + ${QUIET}${CXX} ${INCLUDES} ${COMMON_FLAGS} ${CXXFLAGS} \ + -Lext/libopencm3/lib -Wl,--gc-sections \ + -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group \ + -T src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld \ + ${OBJECTS} -lopencm3_lm4f \ + -o $@ + ${QUIET}${SIZE} build/system.elf | tail -n1 | awk '{ print " ROM: " ($$1+$$2) " (" int(($$1+$$2)*100/49152) "%) RAM: " ($$2 + $$3) " (" int(($$2+$$3)*100/4096) "%)" }' + +program: build/system.elf + ${OBJCOPY} -O binary build/system.elf build/system.bin + lm4flash build/system.bin + +arch_clean: + ${QUIET}rm -f ${OBJECTS} + +cat: + ${QUIET}script/cat.py /dev/${SERIAL_PORT} 115200 ${cpu_freq} 65536 + +monitor: + ${QUIET}screen /dev/${SERIAL_PORT} 115200 + +arch_help: + @echo "lm4f120h5qr-stellaris specific flags:" + +arch_info: + @echo "CPU Freq: ${cpu_freq} Hz" + @echo "Timer Freq: ${timer_freq} Hz" + @echo "I2C Freq: ${i2c_freq} Hz" + @echo "Counter Overflow: 65536/255" + @echo "Monitor: /dev/${SERIAL_PORT} 115200" + +attributes: build/system.elf + ${QUIET}script/size.py ${SIZE} text,data data,bss + +.PHONY: arch_clean arch_help arch_info attributes cat monitor program diff --git a/src/arch/lm4f120h5qr-stellaris/arch.cc b/src/arch/lm4f120h5qr-stellaris/arch.cc new file mode 100644 index 0000000..c87af2f --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/arch.cc @@ -0,0 +1,79 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "arch.h" + +#ifdef TIMER_S +#include "driver/uptime.h" +#endif + +extern "C" { +#include "lm4f_cpp_wrapper.h" +}; + +#ifdef __acweaving +#define __delay_cycles(x) +#endif + +void Arch::setup(void) +{ + arch_clock_init(); +#if defined(WITH_LOOP) + arch_init_loop(); +#endif +} + +#ifdef WITH_WAKEUP +extern void wakeup(); +#endif + +#if defined(WITH_LOOP) +extern void loop(); +extern volatile char run_loop; +#endif + +// for 80 MHz +void Arch::delay_us(unsigned int const us) +{ + volatile int x = us * 77; + while (x--) { + __asm("nop"); + } +} +void Arch::delay_ms(unsigned int const ms) +{ + for (unsigned int i = 0; i < ms; i++) { + volatile int x = 10000; + while (x--) { + __asm("nop"); + } + } +} + +void Arch::idle_loop(void) +{ + while (1) { + __asm__("wfi"); +#ifdef WITH_LOOP + if (run_loop) { +#ifdef TIMER_S + uptime.tick_s(); +#endif + loop(); + run_loop = 0; + } +#endif + } +} + +void Arch::idle(void) +{ + __asm__("wfi"); +#ifdef WITH_WAKEUP + wakeup(); +#endif +} + +Arch arch; diff --git a/src/arch/lm4f120h5qr-stellaris/driver/gpio.cc b/src/arch/lm4f120h5qr-stellaris/driver/gpio.cc new file mode 100644 index 0000000..5b17f1e --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/driver/gpio.cc @@ -0,0 +1,8 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "driver/gpio.h" + +GPIO gpio; diff --git a/src/arch/lm4f120h5qr-stellaris/driver/stdout.cc b/src/arch/lm4f120h5qr-stellaris/driver/stdout.cc new file mode 100644 index 0000000..18b6da4 --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/driver/stdout.cc @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "driver/stdout.h" + +extern "C" { +#include "lm4f_cpp_wrapper.h" +}; + + +void StandardOutput::setup() +{ + mp_uart_setup(); +} + +void StandardOutput::put(char c) +{ + mp_uart_send_blocking(c); + if (c == '\n') { + put('\r'); + } +} + +StandardOutput kout; diff --git a/src/arch/lm4f120h5qr-stellaris/driver/uptime.cc b/src/arch/lm4f120h5qr-stellaris/driver/uptime.cc new file mode 100644 index 0000000..7e37a7b --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/driver/uptime.cc @@ -0,0 +1,8 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include "driver/uptime.h" + +Uptime uptime; diff --git a/src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld b/src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld new file mode 100644 index 0000000..0bc8fe2 --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/lm4f120h5qr.ld @@ -0,0 +1,11 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: CC0-1.0 + */ +MEMORY { + rom (rx) : ORIGIN = 0x00000000, LENGTH = 256K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K +} + +INCLUDE cortex-m-generic.ld diff --git a/src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c b/src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c new file mode 100644 index 0000000..62f1c20 --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/lm4f_cpp_wrapper.c @@ -0,0 +1,177 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + */ +#include +#include +#include +#include +#include +#include +#include + +void arch_clock_init() +{ + // 16MHz Crystal -> 400 MHz PLL -> 80 MHz (/5) + rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, 5); +} + +#ifdef WITH_LOOP +volatile char run_loop = 1; + +void arch_init_loop() +{ + systick_clear(); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + systick_set_frequency(2, F_CPU); + systick_counter_enable(); + systick_interrupt_enable(); + + //periph_clock_enable(RCC_TIMER3); +} + +void sys_tick_handler() +{ + run_loop = 1; +} +#endif + +void mp_uart_setup() +{ + gpio_set_af(GPIOA, 1, GPIO0 | GPIO1); + + periph_clock_enable(RCC_UART0); + + __asm__("nop"); + + uart_disable(UART0); + + uart_clock_from_piosc(UART0); + + uart_set_baudrate(UART0, 9600); + uart_set_databits(UART0, 8); + uart_set_parity(UART0, UART_PARITY_NONE); + uart_set_stopbits(UART0, 1); + + uart_enable(UART0); +} + +void mp_uart_send_blocking(char c) +{ + uart_send_blocking(UART0, c); +} + +#define pb_0 8 +#define pc_0 16 +#define pd_0 24 +#define pe_0 32 +#define pf_0 40 +#define PIN_INVALID 45 + +void mp_gpio_setup() +{ + const unsigned int outpins = GPIO1 | GPIO3 | GPIO2; + + gpio_enable_ahb_aperture(); + + periph_clock_enable(RCC_GPIOA); + periph_clock_enable(RCC_GPIOB); + periph_clock_enable(RCC_GPIOC); + periph_clock_enable(RCC_GPIOD); + periph_clock_enable(RCC_GPIOE); + periph_clock_enable(RCC_GPIOF); + + gpio_mode_setup(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, outpins); + gpio_set_output_config(GPIOF, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, outpins); +} + +void mp_gpio_input(unsigned char const pin) +{ + if (pin < pb_0) { + gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << pin); + } else if (pin < pc_0) { + gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << (pin - pb_0)); + } else if (pin < pd_0) { + gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << (pin - pc_0)); + } else if (pin < pe_0) { + gpio_mode_setup(GPIOD, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << (pin - pd_0)); + } else if (pin < pf_0) { + gpio_mode_setup(GPIOE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << (pin - pe_0)); + } else if (pin < PIN_INVALID) { + gpio_mode_setup(GPIOF, GPIO_MODE_INPUT, GPIO_PUPD_NONE, 1 << (pin - pf_0)); + } +} + +void mp_gpio_output(unsigned char const pin) +{ + if (pin < pb_0) { + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << pin); + } else if (pin < pc_0) { + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << (pin - pb_0)); + } else if (pin < pd_0) { + gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << (pin - pc_0)); + } else if (pin < pe_0) { + gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << (pin - pd_0)); + } else if (pin < pf_0) { + gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << (pin - pe_0)); + } else if (pin < PIN_INVALID) { + gpio_mode_setup(GPIOF, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 1 << (pin - pf_0)); + } +} + +unsigned int mp_gpio_read(unsigned char const pin) { + if (pin < pb_0) { + return gpio_read(GPIOA, 1 << pin); + } else if (pin < pc_0) { + return gpio_read(GPIOB, 1 << (pin-pb_0)); + } else if (pin < pd_0) { + return gpio_read(GPIOC, 1 << (pin-pc_0)); + } else if (pin < pe_0) { + return gpio_read(GPIOD, 1 << (pin-pd_0)); + } else if (pin < pf_0) { + return gpio_read(GPIOE, 1 << (pin-pe_0)); + } else if (pin < PIN_INVALID) { + return gpio_read(GPIOF, 1 << (pin-pf_0)); + } +} + +void mp_gpio_write(unsigned char const pin, unsigned char value) { + if (pin < pb_0) { + if (value) { + gpio_port_write(GPIOA, gpio_port_read(GPIOA) | (1 << pin)); + } else { + gpio_port_write(GPIOA, gpio_port_read(GPIOA) & ~(1 << pin)); + } + } else if (pin < pc_0) { + if (value) { + gpio_port_write(GPIOB, gpio_port_read(GPIOB) | (1 << (pin-pb_0))); + } else { + gpio_port_write(GPIOB, gpio_port_read(GPIOB) & ~(1 << (pin-pb_0))); + } + } else if (pin < pd_0) { + if (value) { + gpio_port_write(GPIOC, gpio_port_read(GPIOC) | (1 << (pin-pc_0))); + } else { + gpio_port_write(GPIOC, gpio_port_read(GPIOC) & ~(1 << (pin-pc_0))); + } + } else if (pin < pe_0) { + if (value) { + gpio_port_write(GPIOD, gpio_port_read(GPIOD) | (1 << (pin-pd_0))); + } else { + gpio_port_write(GPIOD, gpio_port_read(GPIOD) & ~(1 << (pin-pd_0))); + } + } else if (pin < pf_0) { + if (value) { + gpio_port_write(GPIOE, gpio_port_read(GPIOE) | (1 << (pin-pe_0))); + } else { + gpio_port_write(GPIOE, gpio_port_read(GPIOE) & ~(1 << (pin-pe_0))); + } + } else if (pin < PIN_INVALID) { + if (value) { + gpio_port_write(GPIOF, gpio_port_read(GPIOF) | (1 << (pin-pf_0))); + } else { + gpio_port_write(GPIOF, gpio_port_read(GPIOF) & ~(1 << (pin-pf_0))); + } + } +} diff --git a/src/arch/lm4f120h5qr-stellaris/prompt b/src/arch/lm4f120h5qr-stellaris/prompt new file mode 100644 index 0000000..335db16 --- /dev/null +++ b/src/arch/lm4f120h5qr-stellaris/prompt @@ -0,0 +1 @@ +LM4F120XL Stellaris Launchpad -- cgit v1.2.3