summaryrefslogtreecommitdiff
path: root/firmware/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/src/main.c')
-rw-r--r--firmware/src/main.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/firmware/src/main.c b/firmware/src/main.c
new file mode 100644
index 0000000..8e39278
--- /dev/null
+++ b/firmware/src/main.c
@@ -0,0 +1,143 @@
+// vim: shiftwidth=4 tabstop=4 noexpandtab
+
+
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/timer.h>
+#include <libopencm3/cm3/nvic.h>
+
+
+static void clock_init(void);
+static void gpio_init(void);
+static void nvic_init(void);
+static void timer_init(void);
+
+void tim2_isr(void);
+
+
+void main(void)
+{
+ clock_init();
+ gpio_init();
+ gpio_clear(GPIOC, GPIO13); // set onboard LED on
+ nvic_init();
+ timer_init();
+
+ while(1); // wait forever
+}
+
+
+static void clock_init(void)
+{
+ // set sysclk to 72 MHz via external 8 MHz crystal
+ rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);
+
+ // enable clocks for GPIO ports B and C
+ rcc_periph_clock_enable(RCC_GPIOB);
+ rcc_periph_clock_enable(RCC_GPIOC);
+
+ // enable clock for timer 2 (blinking)
+ rcc_periph_clock_enable(RCC_TIM2);
+
+ // enable clock for timer 3 (PWM)
+ rcc_periph_clock_enable(RCC_TIM3);
+
+ // enable clock for alternate functions
+ rcc_periph_clock_enable(RCC_AFIO); // TODO is this necessary?
+}
+
+
+static void gpio_init(void)
+{
+ // init PC13 onboard LED for blinking
+ gpio_set_mode(
+ GPIOC,
+ GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL,
+ GPIO13
+ );
+
+ // setup PB0 (connected to TIM3_CH3) for PWM
+ gpio_set_mode(
+ GPIOB,
+ GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
+ GPIO_TIM3_CH3
+ );
+}
+
+
+static void nvic_init(void)
+{
+ // enable timer 2 interrupt and set priority
+ nvic_enable_irq(NVIC_TIM2_IRQ);
+ nvic_set_priority(NVIC_TIM2_IRQ, 1);
+}
+
+
+static void timer_init(void)
+{
+ // setup timer 2 for blinking
+ timer_set_counter(TIM2, 1);
+ timer_set_prescaler(TIM2, 1440);
+ timer_set_period(TIM2, 50);
+
+ // enable timer / counter 2 and the corresponding interrupt for blinking
+ timer_enable_irq(TIM2, TIM_DIER_UIE);
+ timer_enable_counter(TIM2);
+
+ /*
+ enable timer / counter 3
+ */
+
+ /* Clock division and mode */
+ TIM3_CR1 = TIM_CR1_CKD_CK_INT | TIM_CR1_CMS_EDGE;
+ /* Period */
+ TIM3_ARR = 65535;
+ /* Prescaler */
+ TIM3_PSC = 0;
+ TIM3_EGR = TIM_EGR_UG;
+
+ /* ---- */
+ /* Output compare 3 mode and preload */
+ TIM3_CCMR2 |= TIM_CCMR2_OC3M_PWM1 | TIM_CCMR2_OC3PE;
+
+ /* Polarity and state */
+ TIM3_CCER |= TIM_CCER_CC3P | TIM_CCER_CC3E;
+ //TIM3_CCER |= TIM_CCER_CC3E;
+
+ /* Capture compare value */
+ TIM3_CCR3 = 30000;
+
+ /* ---- */
+ /* ARR reload enable */
+ TIM3_CR1 |= TIM_CR1_ARPE;
+
+ /* Counter enable */
+ TIM3_CR1 |= TIM_CR1_CEN;
+}
+
+
+void tim2_isr(void)
+{
+ // PWM handling
+ static uint32_t pwm_value;
+ if (pwm_value == 0) {
+ pwm_value = 65535;
+ }
+ else {
+ pwm_value -= 20;
+ }
+ TIM3_CCR3 = pwm_value;
+
+ // toggle blink LED
+ static uint32_t counter;
+ counter += 1;
+ if (counter > 500) {
+ gpio_toggle(GPIOC, GPIO13);
+ counter = 0;
+ }
+
+ // clear interrrupt flag
+ TIM_SR(TIM2) &= ~TIM_SR_UIF;
+}