Merge pull request #79 "More L1 support (and f2/f4 rtc)"

Merge remote-tracking branch 'karlp/pr_more_l1_rtc'
This commit is contained in:
Piotr Esden-Tempski
2013-02-18 14:06:02 -08:00
36 changed files with 1858 additions and 290 deletions

View File

@@ -19,7 +19,7 @@
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/rtc.h>
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/cm3/nvic.h>

View File

@@ -20,7 +20,7 @@
#include <libopencm3/stm32/f1/rcc.h>
#include <libopencm3/stm32/f1/gpio.h>
#include <libopencm3/stm32/f1/rtc.h>
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/cm3/nvic.h>

View File

@@ -0,0 +1,24 @@
##
## This file is part of the libopencm3 project.
##
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
##
## 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 <http://www.gnu.org/licenses/>.
##
BINARY = main
LDSCRIPT = ../../../../../lib/stm32/l1/stm32l15xxb.ld
include ../../Makefile.include

View File

@@ -0,0 +1,18 @@
This is _functionally_ identical to the "button-irq-printf"
example, but has been modified to use some low power features.
There is a 115200@8n1 console on PA2, which prints a tick count every second,
and when the user push button is pressed, the time it is held down for is
timed (in milliseconds)
Instead of free running timers and busy loops, this version uses the RTC
module and attempts to sleep as much as possible, including while the button
is pressed.
Status
~~~~~~
Only very basic power savings are done!
Current consumption, led off/on, 16Mhz HSI: 2.7mA/5.4mA
Current consumption, led off/on, 4Mhz HSI: 1.4mA/?.?mA
Current consumption, led off/on, 4Mhz MSI: 0.9mA/?.?mA

View File

@@ -0,0 +1,300 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/stm32/dbgmcu.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/pwr.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/usart.h>
#include <libopencm3/stm32/rtc.h>
#include <libopencm3/stm32/l1/rcc.h>
#include <libopencm3/stm32/l1/flash.h>
#include "syscfg.h"
static volatile struct state_t state;
__attribute__((always_inline)) static inline void __WFI(void)
{
__asm volatile ("wfi");
}
void gpio_setup(void)
{
/* green led for ticking, blue for button feedback */
gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_GREEN_PIN);
gpio_mode_setup(LED_DISCO_BLUE_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_BLUE_PIN);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
}
void BUTTON_DISCO_USER_isr(void)
{
exti_reset_request(BUTTON_DISCO_USER_EXTI);
state.pressed = true;
if (state.falling) {
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
state.hold_time = TIM_CNT(TIMER_BUTTON_PRESS);
} else {
state.falling = true;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_FALLING);
state.hold_time = TIM_CNT(TIMER_BUTTON_PRESS) = 0;
}
}
void setup_buttons(void)
{
/* Enable EXTI0 interrupt. */
nvic_enable_irq(BUTTON_DISCO_USER_NVIC);
gpio_mode_setup(BUTTON_DISCO_USER_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BUTTON_DISCO_USER_PIN);
/* Configure the EXTI subsystem. */
exti_select_source(BUTTON_DISCO_USER_EXTI, BUTTON_DISCO_USER_PORT);
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
exti_enable_request(BUTTON_DISCO_USER_EXTI);
}
void usart_setup(void)
{
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.
* @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;
}
/*
* Free running ms timer.
*/
void setup_button_press_timer(void)
{
timer_reset(TIMER_BUTTON_PRESS);
timer_set_prescaler(TIMER_BUTTON_PRESS, 3999); // 4Mhz/1000hz - 1
timer_set_period(TIMER_BUTTON_PRESS, 0xffff);
timer_enable_counter(TIMER_BUTTON_PRESS);
}
int setup_rtc(void)
{
/* turn on power block to enable unlocking */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_PWREN);
pwr_disable_backup_domain_write_protect();
/* reset rtc */
RCC_CSR |= RCC_CSR_RTCRST;
RCC_CSR &= ~RCC_CSR_RTCRST;
/* We want to use the LSE fitted on the discovery board */
rcc_osc_on(LSE);
rcc_wait_for_osc_ready(LSE);
/* Select the LSE as rtc clock */
rcc_rtc_select_clock(RCC_CSR_RTCSEL_LSE);
/* ?! Stdperiph examples don't turn this on until _afterwards_ which
* simply doesn't work. It must be on at least to be able to configure it */
RCC_CSR |= RCC_CSR_RTCEN;
rtc_unlock();
/* enter init mode */
RTC_ISR |= RTC_ISR_INIT;
while ((RTC_ISR & RTC_ISR_INITF) == 0)
;
/* set synch prescaler, using defaults for 1Hz out */
u32 sync = 255;
u32 async = 127;
rtc_set_prescaler(sync, async);
/* load time and date here if desired, and hour format */
/* exit init mode */
RTC_ISR &= ~(RTC_ISR_INIT);
/* and write protect again */
rtc_lock();
/* and finally enable the clock */
RCC_CSR |= RCC_CSR_RTCEN;
/* And wait for synchro.. */
rtc_wait_for_synchro();
return 0;
}
int setup_rtc_wakeup(int period)
{
rtc_unlock();
/* ensure wakeup timer is off */
RTC_CR &= ~RTC_CR_WUTE;
/* Wait until we can write */
while ((RTC_ISR & RTC_ISR_WUTWF) == 0)
;
RTC_WUTR = period - 1;
/* Use the 1Hz clock as source */
RTC_CR &= ~(RTC_CR_WUCLKSEL_MASK << RTC_CR_WUCLKSEL_SHIFT);
RTC_CR |= (RTC_CR_WUCLKSEL_SPRE << RTC_CR_WUCLKSEL_SHIFT);
/* Restart WakeUp unit */
RTC_CR |= RTC_CR_WUTE;
/* interrupt configuration */
/* also, let's have an interrupt */
RTC_CR |= RTC_CR_WUTIE;
/* done with rtc registers, lock them again */
rtc_lock();
nvic_enable_irq(NVIC_RTC_WKUP_IRQ);
// EXTI configuration
/* Configure the EXTI subsystem. */
// not needed, this chooses ports exti_select_source(EXTI20, BUTTON_DISCO_USER_PORT);
exti_set_trigger(EXTI20, EXTI_TRIGGER_RISING);
exti_enable_request(EXTI20);
return 0;
}
void rtc_wkup_isr(void)
{
/* clear flag, not write protected */
RTC_ISR &= ~(RTC_ISR_WUTF);
exti_reset_request(EXTI20);
state.rtc_ticked = true;
}
int process_state(volatile struct state_t *st)
{
if (st->rtc_ticked) {
st->rtc_ticked = 0;
printf("Tick: %x\n", (unsigned int) RTC_TR);
#if FULL_USER_EXPERIENCE
gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
#else
gpio_clear(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
#endif
}
if (st->pressed) {
st->pressed = false;
if (st->falling) {
gpio_set(LED_DISCO_BLUE_PORT, LED_DISCO_BLUE_PIN);
printf("Pushed down!\n");
} else {
gpio_clear(LED_DISCO_BLUE_PORT, LED_DISCO_BLUE_PIN);
printf("held: %u ms\n", st->hold_time);
}
}
return 0;
}
void reset_clocks(void)
{
/* 4MHz MSI raw range 2*/
clock_scale_t myclock_config = {
.hpre = RCC_CFGR_HPRE_SYSCLK_NODIV,
.ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV,
.ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV,
.voltage_scale = RANGE2,
.flash_config = FLASH_LATENCY_0WS,
.apb1_frequency = 4194000,
.apb2_frequency = 4194000,
.msi_range = RCC_ICSCR_MSIRANGE_4MHZ,
};
rcc_clock_setup_msi(&myclock_config);
/* buttons and uarts */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
/* user feedback leds */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* And a timers for button presses */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM7EN);
}
int main(void)
{
reset_clocks();
gpio_setup();
usart_setup();
setup_buttons();
setup_button_press_timer();
printf("we're awake!\n");
setup_rtc();
setup_rtc_wakeup(1);
while (1) {
PWR_CR |= PWR_CR_LPSDSR;
pwr_set_stop_mode();
__WFI();
reset_clocks();
process_state(&state);
}
return 0;
}

View File

@@ -0,0 +1,61 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef SYSCFG_H
#define SYSCFG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/usart.h>
#define USART_CONSOLE USART2
#define USE_NASTYLOG 1
#define LED_DISCO_GREEN_PORT GPIOB
#define LED_DISCO_GREEN_PIN GPIO7
#define LED_DISCO_BLUE_PORT GPIOB
#define LED_DISCO_BLUE_PIN GPIO6
#define BUTTON_DISCO_USER_PORT GPIOA
#define BUTTON_DISCO_USER_PIN GPIO0
#define BUTTON_DISCO_USER_EXTI EXTI0
#define BUTTON_DISCO_USER_isr exti0_isr
#define BUTTON_DISCO_USER_NVIC NVIC_EXTI0_IRQ
#define TIMER_BUTTON_PRESS TIM7
struct state_t {
bool falling;
bool pressed;
int rtc_ticked;
int hold_time;
};
#ifdef __cplusplus
}
#endif
#endif /* SYSCFG_H */

View File

@@ -1,3 +1,35 @@
* Prints to the screen when the button is pushed/released (irq driven)
115200@8n1 console on PA2 (tx only)
* uses basic timer 6 with overflows to generate a 1ms counter (not an ideal
use, but shows some api methods and can be demoed on the disco board)
* uses basic timer 7 with the exti interrupts to do ghetto input capture.
Not as fast or precise as the real input capture modes, but can be used
on any gpio pin.
No effort at saving power is made here. Current consumption on the Disco board
is ~7.5mA when the green tick led is off, and about 10.5mA when it is on.
example output:
hi guys!
TICK 0
TICK 1
TICK 2
Pushed down!
held: 443 ms
Pushed down!
TICK 3
held: 217 ms
Pushed down!
held: 99 ms
Pushed down!
TICK 4
held: 73 ms
Pushed down!
held: 60 ms
TICK 5
Pushed down!
held: 98 ms
Pushed down!

View File

@@ -1,5 +1,20 @@
/*
* Karl Palsson, 2012 <karlp@tweak.net.au
* This file is part of the libopencm3 project.
*
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <errno.h>
@@ -7,43 +22,55 @@
#include <unistd.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/l1/rcc.h>
#include <libopencm3/stm32/l1/gpio.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/usart.h>
#include "syscfg.h"
static struct state_t state;
void clock_setup(void) {
/* Lots of things on all ports... */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN);
void clock_setup(void)
{
rcc_clock_setup_pll(&clock_config[CLOCK_VRANGE1_HSI_PLL_24MHZ]);
/* Lots of things on all ports... */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* And timers. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM6EN);
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM7EN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
void gpio_setup(void) {
gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_GREEN_PIN);
void gpio_setup(void)
{
/* green led for ticking, blue for button feedback */
gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_GREEN_PIN);
gpio_mode_setup(LED_DISCO_BLUE_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_BLUE_PIN);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
}
void usart_setup(void) {
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);
void usart_setup(void)
{
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);
/* Finally enable the USART. */
usart_enable(USART_CONSOLE);
}
/**
@@ -53,65 +80,108 @@ void usart_setup(void) {
* @param len
* @return
*/
int _write(int file, char *ptr, int len) {
int i;
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;
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 BUTTON_DISCO_USER_isr(void) {
exti_reset_request(BUTTON_DISCO_USER_EXTI);
if (state.falling) {
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
// ILOG("fell: %d\n", TIM_CNT(TIM7));
puts("fell!\n");
} else {
puts("Rose!\n");
// TIM_CNT(TIM7) = 0;
state.falling = true;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_FALLING);
}
void BUTTON_DISCO_USER_isr(void)
{
exti_reset_request(BUTTON_DISCO_USER_EXTI);
if (state.falling) {
gpio_clear(LED_DISCO_BLUE_PORT, LED_DISCO_BLUE_PIN);
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
unsigned int x = TIM_CNT(TIM7);
printf("held: %u ms\n", x);
} else {
gpio_set(LED_DISCO_BLUE_PORT, LED_DISCO_BLUE_PIN);
printf("Pushed down!\n");
TIM_CNT(TIM7) = 0;
state.falling = true;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_FALLING);
}
}
void setup_buttons(void) {
/* Enable EXTI0 interrupt. */
nvic_enable_irq(BUTTON_DISCO_USER_NVIC);
static volatile int t6ovf = 0;
gpio_mode_setup(BUTTON_DISCO_USER_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BUTTON_DISCO_USER_PIN);
/* Configure the EXTI subsystem. */
exti_select_source(BUTTON_DISCO_USER_EXTI, BUTTON_DISCO_USER_PORT);
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
exti_enable_request(BUTTON_DISCO_USER_EXTI);
void tim6_isr(void)
{
TIM_SR(TIM6) &= ~TIM_SR_UIF;
if (t6ovf++ > 1000) {
printf("TICK %d\n", state.tickcount++);
t6ovf = 0;
gpio_toggle(LED_DISCO_GREEN_PORT, LED_DISCO_GREEN_PIN);
}
}
int main(void) {
int i;
int j = 0;
clock_setup();
gpio_setup();
usart_setup();
puts("hi guys!\n");
setup_buttons();
while (1) {
puts("tick:");
putchar('a' + (j++ % 26));
gpio_toggle(GPIOB, GPIO7); /* LED on/off */
for (i = 0; i < 100000; i++) /* Wait a bit. */
__asm__("NOP");
}
/*
* Another ms timer, this one used to generate an overflow interrupt at 1ms
* It is used to toggle leds and write tick counts
*/
void setup_tim6(void)
{
timer_reset(TIM6);
// 24Mhz / 10khz -1.
timer_set_prescaler(TIM6, 2399); // 24Mhz/10000hz - 1
// 10khz for 10 ticks = 1 khz overflow = 1ms overflow interrupts
timer_set_period(TIM6, 10);
return 0;
nvic_enable_irq(NVIC_TIM6_IRQ);
timer_enable_update_event(TIM6); // default at reset!
timer_enable_irq(TIM6, TIM_DIER_UIE);
timer_enable_counter(TIM6);
}
/*
* Free running ms timer.
*/
void setup_tim7(void)
{
timer_reset(TIM7);
timer_set_prescaler(TIM7, 23999); // 24Mhz/1000hz - 1
timer_set_period(TIM7, 0xffff);
timer_enable_counter(TIM7);
}
void setup_buttons(void)
{
/* Enable EXTI0 interrupt. */
nvic_enable_irq(BUTTON_DISCO_USER_NVIC);
gpio_mode_setup(BUTTON_DISCO_USER_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BUTTON_DISCO_USER_PIN);
/* Configure the EXTI subsystem. */
exti_select_source(BUTTON_DISCO_USER_EXTI, BUTTON_DISCO_USER_PORT);
state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
exti_enable_request(BUTTON_DISCO_USER_EXTI);
}
int main(void)
{
clock_setup();
gpio_setup();
usart_setup();
printf("hi guys!\n");
setup_buttons();
setup_tim6();
setup_tim7();
while (1) {
;
}
return 0;
}

View File

@@ -1,7 +1,20 @@
/*
* General configuration of the device
* This file is part of the libopencm3 project.
*
* Karl Palsson <karlp@tweak.net.au> 2012
* Copyright (C) 2012 Karl Palsson <karlp@tweak.net.au>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef SYSCFG_H
@@ -11,8 +24,8 @@
extern "C" {
#endif
#include <libopencm3/stm32/l1/gpio.h>
#include <libopencm3/stm32/l1/nvic.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/usart.h>
@@ -31,10 +44,10 @@ extern "C" {
#define BUTTON_DISCO_USER_isr exti0_isr
#define BUTTON_DISCO_USER_NVIC NVIC_EXTI0_IRQ
struct state_t {
bool falling;
};
struct state_t {
bool falling;
int tickcount;
};
#ifdef __cplusplus

View File

@@ -22,59 +22,63 @@
#include <libopencm3/stm32/l1/gpio.h>
#include <libopencm3/stm32/usart.h>
void clock_setup(void) {
/* We are running on MSI after boot. */
/* Enable GPIOD clock for LED & USARTs. */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN);
void clock_setup(void)
{
/* We are running on MSI after boot. */
/* Enable GPIOD clock for LED & USARTs. */
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
/* Enable clocks for USART2. */
rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN);
}
void usart_setup(void) {
/* Setup USART2 parameters. */
usart_set_baudrate(USART2, 38400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
void usart_setup(void)
{
/* Setup USART2 parameters. */
usart_set_baudrate(USART2, 38400);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
/* Finally enable the USART. */
usart_enable(USART2);
/* Finally enable the USART. */
usart_enable(USART2);
}
void gpio_setup(void) {
/* Setup GPIO pin GPIO7 on GPIO port B for Green LED. */
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7);
void gpio_setup(void)
{
/* Setup GPIO pin GPIO7 on GPIO port B for Green LED. */
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO7);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
/* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
}
int main(void) {
int i, j = 0, c = 0;
int main(void)
{
int i, j = 0, c = 0;
clock_setup();
gpio_setup();
usart_setup();
clock_setup();
gpio_setup();
usart_setup();
/* Blink the LED (PD12) on the board with every transmitted byte. */
while (1) {
gpio_toggle(GPIOB, GPIO7); /* LED on/off */
usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */
c = (c == 9) ? 0 : c + 1; /* Increment c. */
if ((j++ % 80) == 0) { /* Newline after line full. */
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
for (i = 0; i < 100000; i++) /* Wait a bit. */
__asm__("NOP");
}
/* Blink the LED (PD12) on the board with every transmitted byte. */
while (1) {
gpio_toggle(GPIOB, GPIO7); /* LED on/off */
usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */
c = (c == 9) ? 0 : c + 1; /* Increment c. */
if ((j++ % 80) == 0) { /* Newline after line full. */
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
for (i = 0; i < 100000; i++) /* Wait a bit. */
__asm__("NOP");
}
return 0;
return 0;
}