Skip to content

Commit

Permalink
Update example to use timers as well.
Browse files Browse the repository at this point in the history
This example now exercises timers, EXTI, gpio, irqs as well as demonstrating printf.
It only needs a serial cable in addition to the 32L discovery board
  • Loading branch information
karlp committed Nov 18, 2012
1 parent 20c2a14 commit b2fb224
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 79 deletions.
29 changes: 29 additions & 0 deletions examples/stm32/l1/stm32l-discovery/button-irq-printf/README
@@ -1,3 +1,32 @@
* Prints to the screen when the button is pushed/released (irq driven) * Prints to the screen when the button is pushed/released (irq driven)
115200@8n1 console on PA2 (tx only) 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.

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!



205 changes: 130 additions & 75 deletions examples/stm32/l1/stm32l-discovery/button-irq-printf/main.c
Expand Up @@ -9,41 +9,53 @@
#include <libopencm3/stm32/l1/rcc.h> #include <libopencm3/stm32/l1/rcc.h>
#include <libopencm3/stm32/l1/gpio.h> #include <libopencm3/stm32/l1/gpio.h>
#include <libopencm3/stm32/exti.h> #include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/timer.h>
#include <libopencm3/stm32/usart.h> #include <libopencm3/stm32/usart.h>


#include "syscfg.h" #include "syscfg.h"


static struct state_t state; static struct state_t state;


void clock_setup(void) { void clock_setup(void)
/* Lots of things on all ports... */ {
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOAEN); rcc_clock_setup_pll(&clock_vrange1_config[CLOCK_VRANGE1_HSI_PLL_24MHZ]);
rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_GPIOBEN); /* 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) { void gpio_setup(void)
gpio_mode_setup(LED_DISCO_GREEN_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_DISCO_GREEN_PIN); {
/* 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. */ /* Setup GPIO pins for USART2 transmit. */
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2); gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2);


/* Setup USART2 TX pin as alternate function. */ /* Setup USART2 TX pin as alternate function. */
gpio_set_af(GPIOA, GPIO_AF7, GPIO2); gpio_set_af(GPIOA, GPIO_AF7, GPIO2);
} }


void usart_setup(void) { void usart_setup(void)
usart_set_baudrate(USART_CONSOLE, 115200); {
usart_set_databits(USART_CONSOLE, 8); usart_set_baudrate(USART_CONSOLE, 115200);
usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1); usart_set_databits(USART_CONSOLE, 8);
usart_set_mode(USART_CONSOLE, USART_MODE_TX); usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1);
usart_set_parity(USART_CONSOLE, USART_PARITY_NONE); usart_set_mode(USART_CONSOLE, USART_MODE_TX);
usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE); 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);
} }


/** /**
Expand All @@ -53,65 +65,108 @@ void usart_setup(void) {
* @param len * @param len
* @return * @return
*/ */
int _write(int file, char *ptr, int len) { int _write(int file, char *ptr, int len)
int i; {

int i;
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
for (i = 0; i < len; i++) { if (file == STDOUT_FILENO || file == STDERR_FILENO) {
if (ptr[i] == '\n') { for (i = 0; i < len; i++) {
usart_send_blocking(USART_CONSOLE, '\r'); if (ptr[i] == '\n') {
} usart_send_blocking(USART_CONSOLE, '\r');
usart_send_blocking(USART_CONSOLE, ptr[i]); }
} usart_send_blocking(USART_CONSOLE, ptr[i]);
return i; }
} return i;
errno = EIO; }
return -1; errno = EIO;
return -1;
}

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);
}
}

static volatile int t6ovf = 0;

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);
}
}

/*
* 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);

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);
} }


void BUTTON_DISCO_USER_isr(void) { /*
exti_reset_request(BUTTON_DISCO_USER_EXTI); * Free running ms timer.
if (state.falling) { */
state.falling = false; void setup_tim7(void)
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING); {
// ILOG("fell: %d\n", TIM_CNT(TIM7)); timer_reset(TIM7);
puts("fell!\n"); timer_set_prescaler(TIM7, 23999); // 24Mhz/1000hz - 1
} else { timer_set_period(TIM7, 0xffff);
puts("Rose!\n"); timer_enable_counter(TIM7);
// TIM_CNT(TIM7) = 0;
state.falling = true;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_FALLING);
}
} }


void setup_buttons(void) { void setup_buttons(void)
/* Enable EXTI0 interrupt. */ {
nvic_enable_irq(BUTTON_DISCO_USER_NVIC); /* 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); gpio_mode_setup(BUTTON_DISCO_USER_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, BUTTON_DISCO_USER_PIN);


/* Configure the EXTI subsystem. */ /* Configure the EXTI subsystem. */
exti_select_source(BUTTON_DISCO_USER_EXTI, BUTTON_DISCO_USER_PORT); exti_select_source(BUTTON_DISCO_USER_EXTI, BUTTON_DISCO_USER_PORT);
state.falling = false; state.falling = false;
exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING); exti_set_trigger(BUTTON_DISCO_USER_EXTI, EXTI_TRIGGER_RISING);
exti_enable_request(BUTTON_DISCO_USER_EXTI); exti_enable_request(BUTTON_DISCO_USER_EXTI);
} }


int main(void) { int main(void)
int i; {
int j = 0; clock_setup();
clock_setup(); gpio_setup();
gpio_setup(); usart_setup();
usart_setup(); printf("hi guys!\n");
puts("hi guys!\n"); setup_buttons();
setup_buttons(); setup_tim6();
while (1) { setup_tim7();
puts("tick:"); while (1) {
putchar('a' + (j++ % 26)); ;
gpio_toggle(GPIOB, GPIO7); /* LED on/off */ }
for (i = 0; i < 100000; i++) /* Wait a bit. */
__asm__("NOP"); return 0;
}

return 0;
} }
8 changes: 4 additions & 4 deletions examples/stm32/l1/stm32l-discovery/button-irq-printf/syscfg.h
Expand Up @@ -31,10 +31,10 @@ extern "C" {
#define BUTTON_DISCO_USER_isr exti0_isr #define BUTTON_DISCO_USER_isr exti0_isr
#define BUTTON_DISCO_USER_NVIC NVIC_EXTI0_IRQ #define BUTTON_DISCO_USER_NVIC NVIC_EXTI0_IRQ



struct state_t {
struct state_t { bool falling;
bool falling; int tickcount;
}; };




#ifdef __cplusplus #ifdef __cplusplus
Expand Down

0 comments on commit b2fb224

Please sign in to comment.