From a70bb3d7333866713e2ee489aa45fb8c59b56360 Mon Sep 17 00:00:00 2001 From: Kelvin Ly Date: Sun, 14 Feb 2021 16:16:39 -0500 Subject: [PATCH] Reorganize code somewhat to reduce directory depth; USART is working, working on SysTick now --- .../fw/{ztheta-controller => }/.gitignore | 1 + .../fw/{ztheta-controller => }/Makefile | 8 +-- controller-board/fw/ft232h.cfg | 20 ++++++ .../generated.stm32l011f4p6.ld | 0 controller-board/fw/main.c | 66 ++++++++++++++++++ controller-board/fw/ztheta-controller/main.c | 3 - .../ztheta-controller/ztheta-controller.elf | Bin 100072 -> 0 bytes 7 files changed, 91 insertions(+), 7 deletions(-) rename controller-board/fw/{ztheta-controller => }/.gitignore (64%) rename controller-board/fw/{ztheta-controller => }/Makefile (74%) create mode 100644 controller-board/fw/ft232h.cfg rename controller-board/fw/{ztheta-controller => }/generated.stm32l011f4p6.ld (100%) create mode 100644 controller-board/fw/main.c delete mode 100644 controller-board/fw/ztheta-controller/main.c delete mode 100755 controller-board/fw/ztheta-controller/ztheta-controller.elf diff --git a/controller-board/fw/ztheta-controller/.gitignore b/controller-board/fw/.gitignore similarity index 64% rename from controller-board/fw/ztheta-controller/.gitignore rename to controller-board/fw/.gitignore index ac4d450..b3b36aa 100644 --- a/controller-board/fw/ztheta-controller/.gitignore +++ b/controller-board/fw/.gitignore @@ -1,2 +1,3 @@ bin/ +*.elf *.bin diff --git a/controller-board/fw/ztheta-controller/Makefile b/controller-board/fw/Makefile similarity index 74% rename from controller-board/fw/ztheta-controller/Makefile rename to controller-board/fw/Makefile index 5c90a39..42f77f5 100644 --- a/controller-board/fw/ztheta-controller/Makefile +++ b/controller-board/fw/Makefile @@ -1,4 +1,4 @@ -PROJECT = ztheta-controller +PROJECT = controller BUILD_DIR = bin #SHARED_DIR = @@ -6,13 +6,13 @@ CFILES = main.c # TODO - you will need to edit these two lines! DEVICE=stm32l011f4p6 -OOCD_FILE = board/stm32f4discovery.cfg +OOCD_FILE = ft232h.cfg # You shouldn't have to edit anything below here. VPATH += $(SHARED_DIR) INCLUDES += $(patsubst %,-I%, . $(SHARED_DIR)) -OPENCM3_DIR=../libopencm3 +OPENCM3_DIR=libopencm3 include $(OPENCM3_DIR)/mk/genlink-config.mk -include ../rules.mk +include rules.mk include $(OPENCM3_DIR)/mk/genlink-rules.mk diff --git a/controller-board/fw/ft232h.cfg b/controller-board/fw/ft232h.cfg new file mode 100644 index 0000000..3336bcc --- /dev/null +++ b/controller-board/fw/ft232h.cfg @@ -0,0 +1,20 @@ +adapter driver ftdi +transport select swd +ftdi_vid_pid 0x0403 0x6014 + +ftdi_layout_init 0xfff8 0xfffb + +ftdi_layout_signal SWD_EN -data 0 +ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100 +ftdi_layout_signal nSRST -data 0x0200 -oe 0x0200 + +source [find target/stm32l0.cfg] + +$_TARGETNAME configure -event reset-end { +echo "Remapping Flash to address 0x00000000" +# RCC_APB2ENR <= 0x1 +mww 0x40021034 0x1 +# SYSCFG_CFGR1 <= 0x0 +mww 0x40010000 0x0 +} + diff --git a/controller-board/fw/ztheta-controller/generated.stm32l011f4p6.ld b/controller-board/fw/generated.stm32l011f4p6.ld similarity index 100% rename from controller-board/fw/ztheta-controller/generated.stm32l011f4p6.ld rename to controller-board/fw/generated.stm32l011f4p6.ld diff --git a/controller-board/fw/main.c b/controller-board/fw/main.c new file mode 100644 index 0000000..d9699fe --- /dev/null +++ b/controller-board/fw/main.c @@ -0,0 +1,66 @@ +#include +#include +#include + +#include + +int main(void) { + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + + rcc_periph_clock_enable(RCC_USART2); + + // setup PA5-7 and PB1 for the stepper motor gates + gpio_clear(GPIOA, GPIO5|GPIO6|GPIO7); + gpio_clear(GPIOB, GPIO1); + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5); + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6); + gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7); + gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO1); + + // setup PA2/3 for USART2_RX and USART2_TX + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2|GPIO3); + gpio_set_af(GPIOA, GPIO_AF4, GPIO2|GPIO3); + + // setup USART2 stuff + usart_set_baudrate(USART2, 115200); + usart_set_databits(USART2, 8); + usart_set_stopbits(USART2, USART_STOPBITS_1); + usart_set_mode(USART2, USART_MODE_TX_RX); + usart_set_parity(USART2, USART_PARITY_NONE); + usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); + usart_enable(USART2); + +#if 0 + // if I need more speed than the internal 2 MHz + // setup PA0 as a clock input + rcc_bypass_enable(RCC_HSE); + rcc_osc_on(RCC_HSE); + + rcc_wait_for_osc_ready(RCC_HSE); + rcc_set_sysclk_source(RCC_HSE); +#endif + + // setup systick interrupt + systick_interrupt_disable(); + systick_counter_disable(); + + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + systick_set_reload(rcc_ahb_frequency/100000-1); + systick_clear(); + + systick_interrupt_enable(); + systick_counter_enable(); + + while (1) { + if ((USART_ISR(USART2) & USART_ISR_RXNE) != 0) { + // TODO process byte + uint8_t rx = usart_recv(USART2); + usart_send_blocking(USART2, rx); + } + } +} + +void SysTick_Handler(void); +void SysTick_Handler(void) { +} diff --git a/controller-board/fw/ztheta-controller/main.c b/controller-board/fw/ztheta-controller/main.c deleted file mode 100644 index d633183..0000000 --- a/controller-board/fw/ztheta-controller/main.c +++ /dev/null @@ -1,3 +0,0 @@ -int main(void) { - // TODO -} diff --git a/controller-board/fw/ztheta-controller/ztheta-controller.elf b/controller-board/fw/ztheta-controller/ztheta-controller.elf deleted file mode 100755 index e1b79f60567a4cd263b2b58c11b540f823219b19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100072 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 VG)=FsEBCpV`rbby&wNa|{{uWKNErYC