diff --git a/examples/stm32/l4/stm32l476g-disco/basics/Makefile b/examples/stm32/l4/stm32l476g-disco/basics/Makefile new file mode 100644 index 0000000..5a639f9 --- /dev/null +++ b/examples/stm32/l4/stm32l476g-disco/basics/Makefile @@ -0,0 +1,21 @@ +## +## This file is part of the libopencm3 project. +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +BINARY=basics +DEVICE=stm32l476vg + +include ../../Makefile.include diff --git a/examples/stm32/l4/stm32l476g-disco/basics/README.md b/examples/stm32/l4/stm32l476g-disco/basics/README.md new file mode 100644 index 0000000..1961d84 --- /dev/null +++ b/examples/stm32/l4/stm32l476g-disco/basics/README.md @@ -0,0 +1,8 @@ +This demonstrates some basics on the L476G disco board. + +* printf via usart2 to the attached stlink virtual com port. 115200@8n1 +* pll configuration from hsi +* flash wait state configuration +* basic led blinking +* exti interrupts for buttons +* simple timer usage. diff --git a/examples/stm32/l4/stm32l476g-disco/basics/basics.c b/examples/stm32/l4/stm32l476g-disco/basics/basics.c new file mode 100644 index 0000000..6ae272e --- /dev/null +++ b/examples/stm32/l4/stm32l476g-disco/basics/basics.c @@ -0,0 +1,199 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2018 Karl Palsson + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LED_GREEN_PORT GPIOE +#define LED_GREEN_PIN GPIO8 +#define LED_RED_PORT GPIOB +#define LED_RED_PIN GPIO2 + +/* joysticks are on PA0,1,2,3,5 (center, left, right, up, down) */ +#define JOY_PORT GPIOA +#define JOYC_EXTI EXTI0 +#define JOYC_PIN GPIO0 +#define JOYC_NVIC NVIC_EXTI0_IRQ + +#define USART_CONSOLE USART2 /* PD5/6 , af7 */ + +int _write(int file, char *ptr, int len); + +struct state_t { + bool falling; + int last_hold; + //int tickcount; +}; + +static struct state_t state; + + +static void clock_setup(void) +{ + /* FIXME - this should eventually become a clock struct helper setup */ + rcc_osc_on(RCC_HSI16); + + flash_prefetch_enable(); + flash_set_ws(4); + flash_dcache_enable(); + flash_icache_enable(); + /* 16MHz / 4 = > 4 * 40 = 160MHz VCO => 80MHz main pll */ + rcc_set_main_pll(RCC_PLLCFGR_PLLSRC_HSI16, 4, 40, + 0, 0, RCC_PLLCFGR_PLLR_DIV2); + rcc_osc_on(RCC_PLL); + /* either rcc_wait_for_osc_ready() or do other things */ + + /* Enable clocks for the ports we need */ + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOD); + rcc_periph_clock_enable(RCC_GPIOE); + + /* Enable clocks for peripherals we need */ + rcc_periph_clock_enable(RCC_USART2); + rcc_periph_clock_enable(RCC_TIM7); + rcc_periph_clock_enable(RCC_SYSCFG); + + rcc_set_sysclk_source(RCC_CFGR_SW_PLL); /* careful with the param here! */ + rcc_wait_for_sysclk_status(RCC_PLL); + /* FIXME - eventually handled internally */ + rcc_ahb_frequency = 80e6; + rcc_apb1_frequency = 80e6; + rcc_apb2_frequency = 80e6; +} + +static void usart_setup(void) +{ + /* Setup GPIO pins for USART2 transmit. */ + gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5|GPIO6); + + /* Setup USART2 TX pin as alternate function. */ + gpio_set_af(GPIOD, GPIO_AF7, GPIO5); + + usart_set_baudrate(USART_CONSOLE, 115200); + usart_set_databits(USART_CONSOLE, 8); + usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1); + usart_set_mode(USART_CONSOLE, USART_MODE_TX); + usart_set_parity(USART_CONSOLE, USART_PARITY_NONE); + usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE); + + /* Finally enable the USART. */ + usart_enable(USART_CONSOLE); +} + +/** + * Use USART_CONSOLE as a console. + * This is a syscall for newlib + * @param file + * @param ptr + * @param len + * @return + */ +int _write(int file, char *ptr, int len) +{ + int i; + + if (file == STDOUT_FILENO || file == STDERR_FILENO) { + for (i = 0; i < len; i++) { + if (ptr[i] == '\n') { + usart_send_blocking(USART_CONSOLE, '\r'); + } + usart_send_blocking(USART_CONSOLE, ptr[i]); + } + return i; + } + errno = EIO; + return -1; +} + +void exti0_isr(void) +{ + exti_reset_request(JOYC_EXTI); + if (state.falling) { + gpio_clear(LED_RED_PORT, LED_RED_PIN); + state.falling = false; + state.last_hold = TIM_CNT(TIM7); + exti_set_trigger(JOYC_EXTI, EXTI_TRIGGER_RISING); + } else { + /* pushed */ + gpio_set(LED_RED_PORT, LED_RED_PIN); + state.falling = true; + TIM_CNT(TIM7) = 0; + state.last_hold = 0; + exti_set_trigger(JOYC_EXTI, EXTI_TRIGGER_FALLING); + } +} + +/* + * Free running ms timer. + */ +static void setup_tim7(void) +{ + rcc_periph_reset_pulse(RST_TIM7); + timer_set_prescaler(TIM7, rcc_apb1_frequency / 1e3 - 1); + timer_set_period(TIM7, 0xffff); + timer_enable_counter(TIM7); +} + + +int main(void) +{ + int j = 0; + clock_setup(); + usart_setup(); + printf("hi guys!\n"); + + /* green led for ticking */ + gpio_mode_setup(LED_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, + LED_GREEN_PIN); + /* red led for buttons */ + gpio_mode_setup(LED_RED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, + LED_RED_PIN); + + setup_tim7(); + gpio_mode_setup(JOY_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, JOYC_PIN); + nvic_enable_irq(JOYC_NVIC); + exti_select_source(JOYC_EXTI, JOY_PORT); + state.falling = false; + exti_set_trigger(JOYC_EXTI, EXTI_TRIGGER_RISING); + exti_enable_request(JOYC_EXTI); + + while (1) { + printf("tick: %d\n", j++); + if (state.last_hold) { + printf("button was held for %d ms\n", state.last_hold); + state.last_hold = 0; + } + gpio_toggle(LED_GREEN_PORT, LED_GREEN_PIN); + + for (int i = 0; i < 4000000; i++) { /* Wait a bit. */ + __asm__("NOP"); + } + } + + return 0; +}