Compare commits
31 Commits
52956ae46d
...
3484a7b3f6
@ -0,0 +1,13 @@ |
||||
#pragma once |
||||
|
||||
#include <libopencm3/stm32/timer.h> |
||||
|
||||
struct buzzer { |
||||
uint32_t timer; |
||||
enum tim_oc_id channel; |
||||
}; |
||||
|
||||
void buzzer_init(struct buzzer *buzzer); |
||||
void buzzer_enable(struct buzzer *buzzer); |
||||
void buzzer_disable(struct buzzer *buzzer); |
||||
void buzzer_set_freq(struct buzzer *buzzer, uint32_t freq); |
@ -0,0 +1,10 @@ |
||||
#pragma once |
||||
|
||||
struct led { |
||||
uint32_t port; |
||||
uint32_t pin; |
||||
int invert; |
||||
}; |
||||
|
||||
void led_enable(struct led *led); |
||||
void led_disable(struct led *led); |
@ -0,0 +1,3 @@ |
||||
#pragma once |
||||
|
||||
int shell_alarm(struct console *con, size_t argc, const char **argv); |
@ -0,0 +1,3 @@ |
||||
#pragma once |
||||
|
||||
int shell_buzzer(struct console *con, size_t argc, const char **argv); |
@ -0,0 +1,3 @@ |
||||
#pragma once |
||||
|
||||
int shell_led(struct console *con, size_t argc, const char **argv); |
@ -1,44 +0,0 @@ |
||||
/* This is our reset code (tested).
|
||||
* |
||||
* TODO: integrate fully within code base. |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include <libopencm3/stm32/rcc.h> |
||||
#include <libopencm3/stm32/gpio.h> |
||||
|
||||
static void delay(unsigned ms) |
||||
{ |
||||
unsigned i; |
||||
|
||||
for (i = 0; i < 1000 * ms; ++i) { |
||||
__asm__("nop"); |
||||
} |
||||
} |
||||
|
||||
int main(void) |
||||
{ |
||||
rcc_periph_clock_enable(RCC_GPIOB); |
||||
rcc_periph_clock_enable(RCC_GPIOC); |
||||
|
||||
gpio_mode_setup(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO11); |
||||
gpio_set_output_options(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, GPIO11); |
||||
|
||||
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO8); |
||||
gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO9); |
||||
|
||||
while (1) { |
||||
gpio_set(GPIOB, GPIO11); |
||||
gpio_clear(GPIOC, GPIO8); |
||||
gpio_set(GPIOC, GPIO9); |
||||
delay(5 * 5000); |
||||
|
||||
gpio_clear(GPIOB, GPIO11); |
||||
gpio_set(GPIOC, GPIO8); |
||||
gpio_clear(GPIOC, GPIO9); |
||||
delay(5 * 5000); |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -1,7 +1,10 @@ |
||||
obj-y += source/platform/spi_flash.o
|
||||
obj-y += source/platform/usart.o
|
||||
|
||||
obj-y += source/platform/stm32f0/alarm.o
|
||||
obj-y += source/platform/stm32f0/buzzer.o
|
||||
obj-y += source/platform/stm32f0/gpio.o
|
||||
obj-y += source/platform/stm32f0/led.o
|
||||
obj-y += source/platform/stm32f0/rcc.o
|
||||
obj-y += source/platform/stm32f0/rtc.o
|
||||
obj-y += source/platform/stm32f0/spi.o
|
||||
|
@ -0,0 +1,143 @@ |
||||
#include <libopencm3/cm3/nvic.h> |
||||
#include <libopencm3/stm32/exti.h> |
||||
#include <libopencm3/stm32/rtc.h> |
||||
|
||||
#include <libopencm3/stm32/rcc.h> |
||||
#include <libopencm3/stm32/gpio.h> |
||||
#include <libopencm3/stm32/pwr.h> |
||||
|
||||
#include <rtc.h> |
||||
|
||||
static int reset = 0; |
||||
|
||||
static uint8_t u8_to_bcd(uint8_t val) |
||||
{ |
||||
uint32_t quot = (uint32_t)val / 10; |
||||
uint32_t rem = val - quot * 10; |
||||
|
||||
return (quot << 4) | rem; |
||||
} |
||||
|
||||
static inline uint32_t rtc_to_sec(uint32_t rtc) |
||||
{ |
||||
uint32_t sec; |
||||
|
||||
sec = (rtc & 0xf) + ((rtc >> 4) & 0xf) * 10; |
||||
sec += (((rtc >> 8) & 0xf) + ((rtc >> 12) & 0xf) * 10) * 60; |
||||
sec += (((rtc >> 16) & 0xf) + ((rtc >> 20) & 0xf) * 10) * 3600; |
||||
|
||||
return sec; |
||||
} |
||||
|
||||
static inline uint32_t sec_to_rtc(uint32_t sec) |
||||
{ |
||||
uint32_t rtc; |
||||
uint8_t hour; |
||||
uint8_t min; |
||||
|
||||
sec %= SECS_PER_DAY; |
||||
|
||||
hour = sec / 3600; |
||||
rtc = u8_to_bcd(hour) << 16; |
||||
|
||||
sec -= hour * 3600; |
||||
min = sec / 60; |
||||
rtc |= u8_to_bcd(min) << 8; |
||||
|
||||
sec -= min * 60; |
||||
rtc |= u8_to_bcd(sec); |
||||
|
||||
return rtc; |
||||
} |
||||
|
||||
static void rtc_enable_alarm_interrupt(void) |
||||
{ |
||||
exti_enable_request(EXTI17); |
||||
exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); |
||||
|
||||
nvic_enable_irq(NVIC_RTC_IRQ); |
||||
nvic_set_priority(NVIC_RTC_IRQ, 1); |
||||
|
||||
RTC_CR |= RTC_CR_ALRAIE; |
||||
} |
||||
|
||||
static void rtc_disable_alarm_interrupt(void) |
||||
{ |
||||
exti_disable_request(EXTI17); |
||||
|
||||
nvic_disable_irq(NVIC_RTC_IRQ); |
||||
|
||||
RTC_CR &= ~RTC_CR_ALRAIE; |
||||
} |
||||
|
||||
void rtc_isr(void) |
||||
{ |
||||
uint32_t alarm_sec; |
||||
|
||||
gpio_toggle(GPIOC, GPIO8); |
||||
|
||||
pwr_disable_backup_domain_write_protect(); |
||||
rtc_unlock(); |
||||
|
||||
/* Disable the alarm. */ |
||||
RTC_CR &= ~RTC_CR_ALRAE; |
||||
RTC_ISR &= ~RTC_ISR_ALRAF; |
||||
exti_reset_request(EXTI17); |
||||
|
||||
if (!reset) { |
||||
reset = 1; |
||||
gpio_set(GPIOA, GPIO1); |
||||
|
||||
/* Set the alarm time. */ |
||||
alarm_sec = rtc_to_sec(RTC_TR); |
||||
(volatile void)RTC_DR; |
||||
RTC_ALRMAR = sec_to_rtc(alarm_sec + 5) | 0xc0000000; |
||||
|
||||
/* Enable the alarm. */ |
||||
RTC_CR |= RTC_CR_ALRAE; |
||||
} else { |
||||
reset = 0; |
||||
gpio_clear(GPIOA, GPIO1); |
||||
alarm_disable(); |
||||
} |
||||
|
||||
rtc_lock(); |
||||
pwr_enable_backup_domain_write_protect(); |
||||
} |
||||
|
||||
int alarm_enable(uint32_t timeout) |
||||
{ |
||||
uint32_t alarm_sec; |
||||
|
||||
pwr_disable_backup_domain_write_protect(); |
||||
rtc_unlock(); |
||||
|
||||
/* Set the alarm time. */ |
||||
alarm_sec = rtc_to_sec(RTC_TR); |
||||
(volatile void)RTC_DR; |
||||
RTC_ALRMAR = sec_to_rtc(alarm_sec + timeout) | 0xc0000000; |
||||
|
||||
RTC_CR |= RTC_CR_ALRAE; |
||||
rtc_enable_alarm_interrupt(); |
||||
|
||||
rtc_lock(); |
||||
pwr_enable_backup_domain_write_protect(); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int alarm_disable(void) |
||||
{ |
||||
gpio_set(GPIOC, GPIO8); |
||||
|
||||
pwr_disable_backup_domain_write_protect(); |
||||
rtc_unlock(); |
||||
|
||||
RTC_CR &= ~RTC_CR_ALRAE; |
||||
rtc_disable_alarm_interrupt(); |
||||
|
||||
rtc_lock(); |
||||
pwr_enable_backup_domain_write_protect(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,51 @@ |
||||
#include <libopencm3/stm32/gpio.h> |
||||
#include <libopencm3/stm32/rcc.h> |
||||
#include <libopencm3/stm32/timer.h> |
||||
|
||||
#include <buzzer.h> |
||||
#include <macros.h> |
||||
|
||||
struct buzzer buzzers[] = { |
||||
{ TIM1, TIM_OC1 }, |
||||
{ TIM2, TIM_OC2 }, |
||||
{ TIM3, TIM_OC1 }, |
||||
{ TIM14, TIM_OC1 }, |
||||
}; |
||||
|
||||
size_t nbuzzers = count_of(buzzers); |
||||
|
||||
void buzzer_init(struct buzzer *buzzer) |
||||
{ |
||||
timer_reset(buzzer->timer); |
||||
|
||||
timer_set_mode(buzzer->timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); |
||||
|
||||
timer_set_prescaler(buzzer->timer, 48); |
||||
timer_set_repetition_counter(buzzer->timer, 0); |
||||
timer_enable_preload(buzzer->timer); |
||||
timer_enable_break_main_output(buzzer->timer); |
||||
timer_continuous_mode(buzzer->timer); |
||||
|
||||
timer_disable_oc_output(buzzer->timer, buzzer->channel); |
||||
timer_set_oc_mode(buzzer->timer, buzzer->channel, TIM_OCM_PWM1); |
||||
timer_set_oc_value(buzzer->timer, buzzer->channel, 0); |
||||
timer_enable_oc_output(buzzer->timer, buzzer->channel); |
||||
} |
||||
|
||||
void buzzer_enable(struct buzzer *buzzer) |
||||
{ |
||||
timer_enable_counter(buzzer->timer); |
||||
} |
||||
|
||||
void buzzer_disable(struct buzzer *buzzer) |
||||
{ |
||||
timer_disable_counter(buzzer->timer); |
||||
} |
||||
|
||||
void buzzer_set_freq(struct buzzer *buzzer, uint32_t freq) |
||||
{ |
||||
uint32_t period = 1000000 / freq; |
||||
|
||||
timer_set_period(buzzer->timer, period); |
||||
timer_set_oc_value(buzzer->timer, buzzer->channel, period / 2); |
||||
} |
@ -0,0 +1,31 @@ |
||||
#include <libopencm3/stm32/gpio.h> |
||||
|
||||
#include <led.h> |
||||
#include <macros.h> |
||||
|
||||
struct led leds[] = { |
||||
{ GPIOC, GPIO8, 0 }, |
||||
}; |
||||
size_t nleds = count_of(leds); |
||||
|
||||
void led_enable(struct led *led) |
||||
{ |
||||
if (!led) |
||||
return; |
||||
|
||||
if (led->invert) |
||||
gpio_clear(led->port, led->pin); |
||||
else |
||||
gpio_set(led->port, led->pin); |
||||
} |
||||
|
||||
void led_disable(struct led *led) |
||||
{ |
||||
if (!led) |
||||
return; |
||||
|
||||
if (led->invert) |
||||
gpio_set(led->port, led->pin); |
||||
else |
||||
gpio_clear(led->port, led->pin); |
||||
} |
@ -1,7 +1,10 @@ |
||||
obj-y += source/platform/spi_flash.o
|
||||
obj-y += source/platform/usart.o
|
||||
|
||||
obj-y += source/platform/stm32f1/alarm.o
|
||||
obj-y += source/platform/stm32f1/buzzer.o
|
||||
obj-y += source/platform/stm32f1/gpio.o
|
||||
obj-y += source/platform/stm32f1/led.o
|
||||
obj-y += source/platform/stm32f1/rcc.o
|
||||
obj-y += source/platform/stm32f1/rtc.o
|
||||
obj-y += source/platform/stm32f1/spi.o
|
||||
|
@ -0,0 +1,56 @@ |
||||
#include <libopencm3/cm3/nvic.h> |
||||
#include <libopencm3/stm32/exti.h> |
||||
#include <libopencm3/stm32/gpio.h> |
||||
#include <libopencm3/stm32/rtc.h> |
||||
|
||||
#include <rtc.h> |
||||
|
||||
static int reset = 0; |
||||
|
||||
void rtc_alarm_isr(void) |
||||
{ |
||||
if (rtc_check_flag(RTC_ALR)) { |
||||
rtc_clear_flag(RTC_ALR); |
||||
|
||||
rtc_disable_alarm(); |
||||
exti_reset_request(EXTI17); |
||||
|
||||
if (!reset) { |
||||
reset = 1; |
||||
gpio_set(GPIOA, GPIO1); |
||||
|
||||
rtc_set_alarm_time(rtc_get_counter_val() + 5); |
||||
rtc_enable_alarm(); |
||||
} else { |
||||
reset = 0; |
||||
gpio_set(GPIOA, GPIO1); |
||||
alarm_disable(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
int alarm_enable(uint32_t timeout) |
||||
{ |
||||
rtc_enable_alarm(); |
||||
rtc_set_alarm_time(rtc_get_counter_val() + timeout); |
||||
|
||||
exti_enable_request(EXTI17); |
||||
exti_set_trigger(EXTI17, EXTI_TRIGGER_RISING); |
||||
|
||||
nvic_enable_irq(NVIC_RTC_ALARM_IRQ); |
||||
nvic_set_priority(NVIC_RTC_ALARM_IRQ, 1); |
||||
|
||||
rtc_interrupt_enable(RTC_ALR); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int alarm_disable(void) |
||||
{ |
||||
exti_disable_request(EXTI17); |
||||
nvic_disable_irq(NVIC_RTC_ALARM_IRQ); |
||||
rtc_interrupt_disable(RTC_ALR); |
||||
rtc_disable_alarm(); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,49 @@ |
||||
#include <libopencm3/stm32/gpio.h> |
||||
#include <libopencm3/stm32/rcc.h> |
||||
#include <libopencm3/stm32/timer.h> |
||||
|
||||
#include <buzzer.h> |
||||
#include <macros.h> |
||||
|
||||
struct buzzer buzzers[] = { |
||||
{ TIM2, TIM_OC1 }, |
||||
}; |
||||
|
||||
size_t nbuzzers = count_of(buzzers); |
||||
|
||||
void buzzer_init(struct buzzer *buzzer) |
||||
{ |
||||
timer_reset(buzzer->timer); |
||||
|
||||
timer_set_mode(buzzer->timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, |
||||
TIM_CR1_DIR_UP); |
||||
|
||||
timer_set_prescaler(buzzer->timer, 72); |
||||
timer_set_repetition_counter(buzzer->timer, 0); |
||||
timer_enable_preload(buzzer->timer); |
||||
timer_enable_break_main_output(buzzer->timer); |
||||
timer_continuous_mode(buzzer->timer); |
||||
|
||||
timer_disable_oc_output(buzzer->timer, buzzer->channel); |
||||
timer_set_oc_mode(buzzer->timer, buzzer->channel, TIM_OCM_PWM1); |
||||
timer_set_oc_value(buzzer->timer, buzzer->channel, 0); |
||||
timer_enable_oc_output(buzzer->timer, buzzer->channel); |
||||
} |
||||
|
||||
void buzzer_enable(struct buzzer *buzzer) |
||||
{ |
||||
timer_enable_counter(buzzer->timer); |
||||
} |
||||
|
||||
void buzzer_disable(struct buzzer *buzzer) |
||||
{ |
||||
timer_disable_counter(buzzer->timer); |
||||
} |
||||
|
||||
void buzzer_set_freq(struct buzzer *buzzer, uint32_t freq) |
||||
{ |
||||
uint32_t period = 1000000 / freq; |
||||
|
||||
timer_set_period(buzzer->timer, period); |
||||
timer_set_oc_value(buzzer->timer, buzzer->channel, period / 2); |
||||
} |
@ -0,0 +1,32 @@ |
||||
#include <libopencm3/stm32/gpio.h> |
||||
|
||||
#include <led.h> |
||||
#include <macros.h> |
||||
|
||||
struct led leds[] = { |
||||
{ GPIOC, GPIO10, 1 }, |
||||
}; |
||||
|
||||
size_t nleds = count_of(leds); |
||||
|
||||
void led_enable(struct led *led) |
||||
{ |
||||
if (!led) |
||||
return; |
||||
|
||||
if (led->invert) |
||||
gpio_clear(led->port, led->pin); |
||||
else |
||||
gpio_set(led->port, led->pin); |
||||
} |
||||
|
||||
void led_disable(struct led *led) |
||||
{ |
||||
if (!led) |
||||
return; |
||||
|
||||
if (led->invert) |
||||
gpio_set(led->port, led->pin); |
||||
else |
||||
gpio_clear(led->port, led->pin); |
||||
} |
@ -1,10 +1,17 @@ |
||||
obj-y += source/shell/alarm.o
|
||||
obj-y += source/shell/args.o
|
||||
obj-y += source/shell/boot.o
|
||||
obj-y += source/shell/buzzer.o
|
||||
obj-y += source/shell/cmd.o
|
||||
obj-y += source/shell/echo.o
|
||||
obj-y += source/shell/flash.o
|
||||
obj-y += source/shell/ftl.o
|
||||
obj-y += source/shell/led.o
|
||||
obj-y += source/shell/mufs.o
|
||||
obj-y += source/shell/progress.o
|
||||
obj-y += source/shell/rtc.o
|
||||
obj-y += source/shell/version.o
|
||||
|
||||
ifeq (${TARGET},stm32f1) |
||||
obj-y += source/shell/jtag.o
|
||||
endif |
||||
|
@ -0,0 +1,30 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <libopencm3/stm32/gpio.h> |
||||
|
||||
#include <console.h> |
||||
#include <rtc.h> |
||||
|
||||
int shell_alarm(struct console *con, size_t argc, const char **argv) |
||||
{ |
||||
int state = 0; |
||||
uint32_t timeout = 10; |
||||
|
||||
(void)con; |
||||
|
||||
if (argc >= 2) |
||||
timeout = strtoul(argv[0], NULL, 0); |
||||
|
||||
if (argc >= 1) |
||||
state = (strcmp(argv[1], "on") == 0); |
||||
|
||||
if (state) { |
||||
alarm_enable(timeout); |
||||
} else { |
||||
alarm_disable(); |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,47 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <buzzer.h> |
||||
#include <console.h> |
||||
|
||||
extern struct buzzer buzzers[]; |
||||
extern size_t nbuzzers; |
||||
|
||||
int shell_buzzer(struct console *con, size_t argc, const char **argv) |
||||
{ |
||||
struct buzzer *buzzer; |
||||
size_t buzzer_id = 0; |
||||
uint32_t freq = 0; |
||||
int state = 0; |
||||
|
||||
if (argc >= 3) |
||||
freq = strtoul(argv[2], NULL, 0); |
||||
|
||||
if (argc >= 2) |
||||
state = (strcmp(argv[1], "on") == 0); |
||||
|
||||
if (argc >= 1) |
||||
buzzer_id = strtoul(argv[0], NULL, 0); |
||||
|
||||
fprintf(con->fp, "%u %d %u\n", buzzer_id, state, freq); |
||||
|
||||
if (buzzer_id >= nbuzzers) { |
||||
fprintf(con->fp, "error: invalid buzzer ID %d\n", buzzer_id); |
||||
return -1; |
||||
} |
||||
|
||||
buzzer = buzzers + buzzer_id; |
||||
|
||||
if (!state) { |
||||
buzzer_disable(buzzer); |
||||
return 0; |
||||
} |
||||
|
||||
if (freq) |
||||
buzzer_set_freq(buzzer, freq); |
||||
|
||||
buzzer_enable(buzzer); |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,36 @@ |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include <libopencm3/stm32/gpio.h> |
||||
|
||||
#include <console.h> |
||||
#include <led.h> |
||||
|
||||
extern struct led leds[]; |
||||
extern size_t nleds; |
||||
|
||||
int shell_led(struct console *con, size_t argc, const char **argv) |
||||
{ |
||||
size_t led_id = 0; |
||||
int state = 0; |
||||
|
||||
if (argc >= 2) |
||||
state = (strcmp(argv[1], "on") == 0); |
||||
|
||||
if (argc >= 1) |
||||
led_id = strtoul(argv[0], NULL, 0); |
||||
|
||||
if (led_id >= nleds) { |
||||
fprintf(con->fp, "error: unknown LED ID %d\n", led_id); |
||||
return -1; |
||||
} |
||||
|
||||
if (state) { |
||||
led_enable(leds + led_id); |
||||
} else { |
||||
led_disable(leds + led_id); |
||||
} |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue