From cff706e3ca3823ffb388a4e87c4ef8bf925945c4 Mon Sep 17 00:00:00 2001 From: Fergus Noble Date: Thu, 15 Sep 2011 01:20:45 -0700 Subject: Rename F1 examples folder. --- examples/stm32f1/stm32-h103/button/Makefile | 23 ++ examples/stm32f1/stm32-h103/button/button.c | 79 ++++ examples/stm32f1/stm32-h103/button/button.ld | 31 ++ examples/stm32f1/stm32-h103/exti_both/Makefile | 23 ++ examples/stm32f1/stm32-h103/exti_both/exti_both.c | 92 +++++ examples/stm32f1/stm32-h103/exti_both/exti_both.ld | 31 ++ .../stm32-h103/exti_rising_falling/Makefile | 23 ++ .../exti_rising_falling/exti_rising_falling.c | 98 +++++ .../exti_rising_falling/exti_rising_falling.ld | 31 ++ examples/stm32f1/stm32-h103/fancyblink/Makefile | 23 ++ examples/stm32f1/stm32-h103/fancyblink/README | 10 + .../stm32f1/stm32-h103/fancyblink/fancyblink.c | 55 +++ .../stm32f1/stm32-h103/fancyblink/fancyblink.ld | 31 ++ examples/stm32f1/stm32-h103/led_stripe/Makefile | 23 ++ .../stm32f1/stm32-h103/led_stripe/led_stripe.c | 234 ++++++++++++ .../stm32f1/stm32-h103/led_stripe/led_stripe.ld | 31 ++ examples/stm32f1/stm32-h103/miniblink/Makefile | 23 ++ examples/stm32f1/stm32-h103/miniblink/README | 10 + examples/stm32f1/stm32-h103/miniblink/miniblink.c | 71 ++++ examples/stm32f1/stm32-h103/miniblink/miniblink.ld | 31 ++ examples/stm32f1/stm32-h103/pwm_6step/Makefile | 23 ++ examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.c | 409 +++++++++++++++++++++ examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.ld | 31 ++ examples/stm32f1/stm32-h103/spi/Makefile | 23 ++ examples/stm32f1/stm32-h103/spi/README | 8 + examples/stm32f1/stm32-h103/spi/spi.c | 50 +++ examples/stm32f1/stm32-h103/spi/spi.ld | 31 ++ examples/stm32f1/stm32-h103/timer/Makefile | 23 ++ examples/stm32f1/stm32-h103/timer/timer.c | 183 +++++++++ examples/stm32f1/stm32-h103/timer/timer.ld | 31 ++ examples/stm32f1/stm32-h103/traceswo/Makefile | 23 ++ examples/stm32f1/stm32-h103/traceswo/README | 11 + examples/stm32f1/stm32-h103/traceswo/traceswo.c | 100 +++++ examples/stm32f1/stm32-h103/traceswo/traceswo.ld | 31 ++ examples/stm32f1/stm32-h103/usart/Makefile | 23 ++ examples/stm32f1/stm32-h103/usart/README | 13 + examples/stm32f1/stm32-h103/usart/usart.c | 119 ++++++ examples/stm32f1/stm32-h103/usart/usart.ld | 31 ++ examples/stm32f1/stm32-h103/usart_irq/Makefile | 23 ++ examples/stm32f1/stm32-h103/usart_irq/usart_irq.c | 119 ++++++ examples/stm32f1/stm32-h103/usart_irq/usart_irq.ld | 31 ++ .../stm32f1/stm32-h103/usart_irq_printf/Makefile | 23 ++ .../stm32-h103/usart_irq_printf/usart_irq_printf.c | 272 ++++++++++++++ .../usart_irq_printf/usart_irq_printf.ld | 31 ++ examples/stm32f1/stm32-h103/usart_printf/Makefile | 23 ++ .../stm32f1/stm32-h103/usart_printf/usart_printf.c | 108 ++++++ .../stm32-h103/usart_printf/usart_printf.ld | 31 ++ examples/stm32f1/stm32-h103/usb_cdcacm/Makefile | 23 ++ examples/stm32f1/stm32-h103/usb_cdcacm/README | 7 + examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.c | 246 +++++++++++++ examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.ld | 31 ++ examples/stm32f1/stm32-h103/usb_dfu/Makefile | 23 ++ examples/stm32f1/stm32-h103/usb_dfu/README | 7 + examples/stm32f1/stm32-h103/usb_dfu/usbdfu.c | 270 ++++++++++++++ examples/stm32f1/stm32-h103/usb_dfu/usbdfu.ld | 29 ++ examples/stm32f1/stm32-h103/usb_hid/Makefile | 23 ++ examples/stm32f1/stm32-h103/usb_hid/README | 7 + examples/stm32f1/stm32-h103/usb_hid/usbhid.c | 272 ++++++++++++++ examples/stm32f1/stm32-h103/usb_hid/usbhid.ld | 31 ++ examples/stm32f1/stm32-h103/usb_iap/Makefile | 23 ++ examples/stm32f1/stm32-h103/usb_iap/README | 8 + examples/stm32f1/stm32-h103/usb_iap/usbiap.c | 270 ++++++++++++++ examples/stm32f1/stm32-h103/usb_iap/usbiap.ld | 31 ++ 63 files changed, 4098 insertions(+) create mode 100644 examples/stm32f1/stm32-h103/button/Makefile create mode 100644 examples/stm32f1/stm32-h103/button/button.c create mode 100644 examples/stm32f1/stm32-h103/button/button.ld create mode 100644 examples/stm32f1/stm32-h103/exti_both/Makefile create mode 100644 examples/stm32f1/stm32-h103/exti_both/exti_both.c create mode 100644 examples/stm32f1/stm32-h103/exti_both/exti_both.ld create mode 100644 examples/stm32f1/stm32-h103/exti_rising_falling/Makefile create mode 100644 examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.c create mode 100644 examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.ld create mode 100644 examples/stm32f1/stm32-h103/fancyblink/Makefile create mode 100644 examples/stm32f1/stm32-h103/fancyblink/README create mode 100644 examples/stm32f1/stm32-h103/fancyblink/fancyblink.c create mode 100644 examples/stm32f1/stm32-h103/fancyblink/fancyblink.ld create mode 100644 examples/stm32f1/stm32-h103/led_stripe/Makefile create mode 100644 examples/stm32f1/stm32-h103/led_stripe/led_stripe.c create mode 100644 examples/stm32f1/stm32-h103/led_stripe/led_stripe.ld create mode 100644 examples/stm32f1/stm32-h103/miniblink/Makefile create mode 100644 examples/stm32f1/stm32-h103/miniblink/README create mode 100644 examples/stm32f1/stm32-h103/miniblink/miniblink.c create mode 100644 examples/stm32f1/stm32-h103/miniblink/miniblink.ld create mode 100644 examples/stm32f1/stm32-h103/pwm_6step/Makefile create mode 100644 examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.c create mode 100644 examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.ld create mode 100644 examples/stm32f1/stm32-h103/spi/Makefile create mode 100644 examples/stm32f1/stm32-h103/spi/README create mode 100644 examples/stm32f1/stm32-h103/spi/spi.c create mode 100644 examples/stm32f1/stm32-h103/spi/spi.ld create mode 100644 examples/stm32f1/stm32-h103/timer/Makefile create mode 100644 examples/stm32f1/stm32-h103/timer/timer.c create mode 100644 examples/stm32f1/stm32-h103/timer/timer.ld create mode 100644 examples/stm32f1/stm32-h103/traceswo/Makefile create mode 100644 examples/stm32f1/stm32-h103/traceswo/README create mode 100644 examples/stm32f1/stm32-h103/traceswo/traceswo.c create mode 100644 examples/stm32f1/stm32-h103/traceswo/traceswo.ld create mode 100644 examples/stm32f1/stm32-h103/usart/Makefile create mode 100644 examples/stm32f1/stm32-h103/usart/README create mode 100644 examples/stm32f1/stm32-h103/usart/usart.c create mode 100644 examples/stm32f1/stm32-h103/usart/usart.ld create mode 100644 examples/stm32f1/stm32-h103/usart_irq/Makefile create mode 100644 examples/stm32f1/stm32-h103/usart_irq/usart_irq.c create mode 100644 examples/stm32f1/stm32-h103/usart_irq/usart_irq.ld create mode 100644 examples/stm32f1/stm32-h103/usart_irq_printf/Makefile create mode 100644 examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.c create mode 100644 examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.ld create mode 100644 examples/stm32f1/stm32-h103/usart_printf/Makefile create mode 100644 examples/stm32f1/stm32-h103/usart_printf/usart_printf.c create mode 100644 examples/stm32f1/stm32-h103/usart_printf/usart_printf.ld create mode 100644 examples/stm32f1/stm32-h103/usb_cdcacm/Makefile create mode 100644 examples/stm32f1/stm32-h103/usb_cdcacm/README create mode 100644 examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.c create mode 100644 examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.ld create mode 100644 examples/stm32f1/stm32-h103/usb_dfu/Makefile create mode 100644 examples/stm32f1/stm32-h103/usb_dfu/README create mode 100644 examples/stm32f1/stm32-h103/usb_dfu/usbdfu.c create mode 100644 examples/stm32f1/stm32-h103/usb_dfu/usbdfu.ld create mode 100644 examples/stm32f1/stm32-h103/usb_hid/Makefile create mode 100644 examples/stm32f1/stm32-h103/usb_hid/README create mode 100644 examples/stm32f1/stm32-h103/usb_hid/usbhid.c create mode 100644 examples/stm32f1/stm32-h103/usb_hid/usbhid.ld create mode 100644 examples/stm32f1/stm32-h103/usb_iap/Makefile create mode 100644 examples/stm32f1/stm32-h103/usb_iap/README create mode 100644 examples/stm32f1/stm32-h103/usb_iap/usbiap.c create mode 100644 examples/stm32f1/stm32-h103/usb_iap/usbiap.ld (limited to 'examples/stm32f1/stm32-h103') diff --git a/examples/stm32f1/stm32-h103/button/Makefile b/examples/stm32f1/stm32-h103/button/Makefile new file mode 100644 index 0000000..96731c2 --- /dev/null +++ b/examples/stm32f1/stm32-h103/button/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = button + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/button/button.c b/examples/stm32f1/stm32-h103/button/button.c new file mode 100644 index 0000000..63f3274 --- /dev/null +++ b/examples/stm32f1/stm32-h103/button/button.c @@ -0,0 +1,79 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann , + * 2010 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +u16 exti_line_state; + +/* Set STM32 to 72 MHz. */ +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + +} + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void button_setup(void) +{ + /* Enable GPIOA clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + + /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO0); + +} + +int main(void) +{ + int i; + + clock_setup(); + gpio_setup(); + button_setup(); + + /* Blink the LED (PC12) on the board. */ + while (1) { + gpio_toggle(GPIOC, GPIO12); + + exti_line_state = GPIOA_IDR; + if ((exti_line_state & (1 << 0)) != 0) { + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("nop"); + } + + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/button/button.ld b/examples/stm32f1/stm32-h103/button/button.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/button/button.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/exti_both/Makefile b/examples/stm32f1/stm32-h103/exti_both/Makefile new file mode 100644 index 0000000..39e305b --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_both/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = exti_both + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/exti_both/exti_both.c b/examples/stm32f1/stm32-h103/exti_both/exti_both.c new file mode 100644 index 0000000..edfc676 --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_both/exti_both.c @@ -0,0 +1,92 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann , + * 2010 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +u16 exti_line_state; + +/* Set STM32 to 72 MHz. */ +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + +} + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void exti_setup(void) +{ + /* Enable GPIOA clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + + /* Enable AFIO clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + /* Enable EXTI0 interrupt */ + nvic_enable_irq(NVIC_EXTI0_IRQ); + + /* Set GPIO0 (in GPIO port A) to 'input float'. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO0); + + /* configure EXTI subsystem */ + exti_select_source(EXTI0, GPIOA); + exti_set_trigger(EXTI0, EXTI_TRIGGER_BOTH); + exti_enable_request(EXTI0); +} + +void exti0_isr() +{ + exti_line_state = GPIOA_IDR; + + if ((exti_line_state & (1 << 0)) != 0) { + gpio_clear(GPIOC, GPIO12); + } else { + gpio_set(GPIOC, GPIO12); + } + + exti_reset_request(EXTI0); +} + +int main(void) +{ + + clock_setup(); + gpio_setup(); + exti_setup(); + + /* Blink the LED (PC12) on the board. */ + while (1) { + __asm("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/exti_both/exti_both.ld b/examples/stm32f1/stm32-h103/exti_both/exti_both.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_both/exti_both.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/exti_rising_falling/Makefile b/examples/stm32f1/stm32-h103/exti_rising_falling/Makefile new file mode 100644 index 0000000..fc603a6 --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_rising_falling/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = exti_rising_falling + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.c b/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.c new file mode 100644 index 0000000..af1268d --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.c @@ -0,0 +1,98 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann , + * 2010 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#define FALLING 0 +#define RISING 1 + +u16 exti_direction = FALLING; + +/* Set STM32 to 72 MHz. */ +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + +} + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void exti_setup(void) +{ + /* Enable GPIOA clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + + /* Enable AFIO clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + /* Enable EXTI0 interrupt */ + nvic_enable_irq(NVIC_EXTI0_IRQ); + + /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO0); + + /* configure EXTI subsystem */ + exti_select_source(EXTI0, GPIOA); + exti_direction = FALLING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING); + exti_enable_request(EXTI0); +} + +void exti0_isr() +{ + exti_reset_request(EXTI0); + + if (exti_direction == FALLING) { + gpio_set(GPIOC, GPIO12); + exti_direction = RISING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_RISING); + } else { + gpio_clear(GPIOC, GPIO12); + exti_direction = FALLING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING); + } +} + +int main(void) +{ + + clock_setup(); + gpio_setup(); + exti_setup(); + + /* Blink the LED (PC12) on the board. */ + while (1) { + __asm("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.ld b/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/exti_rising_falling/exti_rising_falling.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/fancyblink/Makefile b/examples/stm32f1/stm32-h103/fancyblink/Makefile new file mode 100644 index 0000000..1baec4d --- /dev/null +++ b/examples/stm32f1/stm32-h103/fancyblink/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = fancyblink + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/fancyblink/README b/examples/stm32f1/stm32-h103/fancyblink/README new file mode 100644 index 0000000..bdb6ec8 --- /dev/null +++ b/examples/stm32f1/stm32-h103/fancyblink/README @@ -0,0 +1,10 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This is small LED blinking example program using libopencm3. + +It's intended for the ST STM32-based Olimex STM32-H103 eval board (see +http://olimex.com/dev/stm32-h103.html for details). It should blink +the LED on the board. + diff --git a/examples/stm32f1/stm32-h103/fancyblink/fancyblink.c b/examples/stm32f1/stm32-h103/fancyblink/fancyblink.c new file mode 100644 index 0000000..eeb3f34 --- /dev/null +++ b/examples/stm32f1/stm32-h103/fancyblink/fancyblink.c @@ -0,0 +1,55 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +/* Set STM32 to 72 MHz. */ +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + +} + +void gpio_setup(void) +{ + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +int main(void) +{ + int i; + + clock_setup(); + gpio_setup(); + + /* Blink the LED (PC12) on the board. */ + while (1) { + gpio_toggle(GPIOC, GPIO12); /* LED on/off */ + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/fancyblink/fancyblink.ld b/examples/stm32f1/stm32-h103/fancyblink/fancyblink.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/fancyblink/fancyblink.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/led_stripe/Makefile b/examples/stm32f1/stm32-h103/led_stripe/Makefile new file mode 100644 index 0000000..60fd1ef --- /dev/null +++ b/examples/stm32f1/stm32-h103/led_stripe/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = led_stripe + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/led_stripe/led_stripe.c b/examples/stm32f1/stm32-h103/led_stripe/led_stripe.c new file mode 100644 index 0000000..9cf9d4f --- /dev/null +++ b/examples/stm32f1/stm32-h103/led_stripe/led_stripe.c @@ -0,0 +1,234 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2011 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* + * This example is implementing the protocol of ZJ168 addressable led + * strips. These strips use the LPD6803 controller. You may be able to + * find the datasheet here: + * http://www.adafruit.com/datasheets/LPD6803.pdf + */ + +#include + +#include +#include + +#define SPI_BANK GPIOB +#define SCLK_PIN GPIO13 +#define MOSI_PIN GPIO15 + +#define SMALL_DELAY_VALUE 0 + +#define COLOR_COUNT 50 + +#define SCLK(VAL) \ + if (VAL) { \ + gpio_set(SPI_BANK, SCLK_PIN); \ + } else { \ + gpio_clear(SPI_BANK, SCLK_PIN); \ + } + +#define MOSI(VAL) \ + if (VAL) { \ + gpio_set(SPI_BANK, MOSI_PIN); \ + } else { \ + gpio_clear(SPI_BANK, MOSI_PIN); \ + } + +#define SMALL_DELAY() { \ + int j; \ + for (j = 0; j < SMALL_DELAY_VALUE; j++) \ + __asm__("nop"); \ + } + +struct color { + u8 r; + u8 g; + u8 b; +}; + +/* Set STM32 to 72 MHz. */ +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + +} + +void gpio_setup(void) +{ + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO13); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); +} + +void send_colors(struct color *colors, int count) { + int i, k; + + /* initialize spi pins */ + SCLK(0); + MOSI(0); + + /* start frame */ + for (i=0; i<32; i++) { + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + } + + /* color cell output */ + for (k = 0; k < count; k++) { + /* Start bit */ + MOSI(1); + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + + /* Blue */ + for (i=0; i<5; i++) { + MOSI(((colors[k].b & ((1 << 4) >> i)) != 0)); + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + } + /* Red */ + for (i=0; i<5; i++) { + MOSI(((colors[k].r & ((1 << 4) >> i)) != 0)); + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + } + /* Green */ + for (i=0; i<5; i++) { + MOSI(((colors[k].g & ((1 << 4) >> i)) != 0)); + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + } + } + + /* End frame */ + MOSI(0); + for (k=0; k < count; k++) { + SCLK(1); + SMALL_DELAY(); + SCLK(0); + SMALL_DELAY(); + } +} + +void reset_colors(struct color *colors, int count) { + int i; + + for (i=0; i + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/miniblink/Makefile b/examples/stm32f1/stm32-h103/miniblink/Makefile new file mode 100644 index 0000000..24a478b --- /dev/null +++ b/examples/stm32f1/stm32-h103/miniblink/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = miniblink + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/miniblink/README b/examples/stm32f1/stm32-h103/miniblink/README new file mode 100644 index 0000000..0e046f2 --- /dev/null +++ b/examples/stm32f1/stm32-h103/miniblink/README @@ -0,0 +1,10 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This is the smallest-possible example program using libopencm3. + +It's intended for the ST STM32-based Olimex STM32-H103 eval board (see +http://olimex.com/dev/stm32-h103.html for details). It should blink +the LED on the board. + diff --git a/examples/stm32f1/stm32-h103/miniblink/miniblink.c b/examples/stm32f1/stm32-h103/miniblink/miniblink.c new file mode 100644 index 0000000..6f8bc2c --- /dev/null +++ b/examples/stm32f1/stm32-h103/miniblink/miniblink.c @@ -0,0 +1,71 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + /* Manually: */ + // RCC_APB2ENR |= RCC_APB2ENR_IOPCEN; + /* Using API functions: */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + /* Manually: */ + // GPIOC_CRH = (GPIO_CNF_OUTPUT_PUSHPULL << (((12 - 8) * 4) + 2)); + // GPIOC_CRH |= (GPIO_MODE_OUTPUT_2_MHZ << ((12 - 8) * 4)); + /* Using API functions: */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +int main(void) +{ + int i; + + gpio_setup(); + + /* Blink the LED (PC12) on the board. */ + while (1) { + /* Manually: */ + // GPIOC_BSRR = GPIO12; /* LED off */ + // for (i = 0; i < 800000; i++) /* Wait a bit. */ + // __asm__("nop"); + // GPIOC_BRR = GPIO12; /* LED on */ + // for (i = 0; i < 800000; i++) /* Wait a bit. */ + // __asm__("nop"); + + /* Using API functions gpio_set()/gpio_clear(): */ + // gpio_set(GPIOC, GPIO12); /* LED off */ + // for (i = 0; i < 800000; i++) /* Wait a bit. */ + // __asm__("nop"); + // gpio_clear(GPIOC, GPIO12); /* LED on */ + // for (i = 0; i < 800000; i++) /* Wait a bit. */ + // __asm__("nop"); + + /* Using API function gpio_toggle(): */ + gpio_toggle(GPIOC, GPIO12); /* LED on/off */ + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/miniblink/miniblink.ld b/examples/stm32f1/stm32-h103/miniblink/miniblink.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/miniblink/miniblink.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/pwm_6step/Makefile b/examples/stm32f1/stm32-h103/pwm_6step/Makefile new file mode 100644 index 0000000..2360082 --- /dev/null +++ b/examples/stm32f1/stm32-h103/pwm_6step/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = pwm_6step + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.c b/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.c new file mode 100644 index 0000000..bda8ff7 --- /dev/null +++ b/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.c @@ -0,0 +1,409 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2011 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#define FALLING 0 +#define RISING 1 + +u16 exti_direction = FALLING; + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + +} + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* + * Set GPIO12 (PORTC) (led) to + * 'output alternate function push-pull'. + */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + +} + +void exti_setup(void) +{ + /* Enable GPIOA clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + + /* Enable AFIO clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + /* Enable EXTI0 interrupt */ + nvic_enable_irq(NVIC_EXTI0_IRQ); + + /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO0); + + /* configure EXTI subsystem */ + exti_select_source(EXTI0, GPIOA); + exti_direction = FALLING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING); + exti_enable_request(EXTI0); +} + +void exti0_isr() +{ + exti_reset_request(EXTI0); + + if (exti_direction == FALLING) { + //gpio_toggle(GPIOA, GPIO12); + exti_direction = RISING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_RISING); + } else { + //gpio_toggle(GPIOA, GPIO12); + timer_generate_event(TIM1, TIM_EGR_COMG); + exti_direction = FALLING; + exti_set_trigger(EXTI0, EXTI_TRIGGER_FALLING); + } +} + +void tim_setup(void) +{ + + /* Enable TIM1 clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_TIM1EN); + + /* Enable GPIOA, GPIOB and Alternate Function clocks. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, + RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_IOPBEN | + RCC_APB2ENR_AFIOEN); + + /* + * Set TIM1 chanel output pins to + * 'output alternate function push-pull'. + */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, + GPIO_TIM1_CH1 | + GPIO_TIM1_CH2 | + GPIO_TIM1_CH3); + + /* + * Set TIM1 complementary chanel output pins to + * 'output alternate function push-pull'. + */ + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, + GPIO_TIM1_CH1N | + GPIO_TIM1_CH2N | + GPIO_TIM1_CH3N); + + /* Enable TIM1 commutation interrupt. */ + nvic_enable_irq(NVIC_TIM1_TRG_COM_IRQ); + + /* Reset TIM1 peripheral */ + timer_reset(TIM1); + + /* Timer global mode: + * - No divider + * - alignment edge + * - direction up + */ + timer_set_mode(TIM1, TIM_CR1_CKD_CK_INT, + TIM_CR1_CMS_EDGE, + TIM_CR1_DIR_UP); + + /* Reset prescaler value. */ + timer_set_prescaler(TIM1, 0); + + /* Reset repetition counter value. */ + timer_set_repetition_counter(TIM1, 0); + + /* Enable preload. */ + timer_enable_preload(TIM1); + + /* Continous mode. */ + timer_continuous_mode(TIM1); + + /* Period (32kHz) */ + timer_set_period(TIM1, 72000000 / 32000); + + /* Configure break and deadtime */ + timer_set_deadtime(TIM1, 10); + timer_set_enabled_off_state_in_idle_mode(TIM1); + timer_set_enabled_off_state_in_run_mode(TIM1); + timer_disable_break(TIM1); + timer_set_break_polarity_high(TIM1); + timer_disable_break_automatic_output(TIM1); + timer_set_break_lock(TIM1, TIM_BDTR_LOCK_OFF); + + /* -- OC1 and OC1N configuration -- */ + + /* Disable outputs. */ + timer_disable_oc_output(TIM1, TIM_OC1); + timer_disable_oc_output(TIM1, TIM_OC1N); + + /* Configure global mode of line 1. */ + timer_disable_oc_clear(TIM1, TIM_OC1); + timer_enable_oc_preload(TIM1, TIM_OC1); + timer_set_oc_slow_mode(TIM1, TIM_OC1); + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); + + /* Configure OC1. */ + timer_set_oc_polarity_high(TIM1, TIM_OC1); + timer_set_oc_idle_state_set(TIM1, TIM_OC1); + + /* Configure OC1N. */ + timer_set_oc_polarity_high(TIM1, TIM_OC1N); + timer_set_oc_idle_state_set(TIM1, TIM_OC1N); + + /* Set the capture compare value for OC1. */ + timer_set_oc_value(TIM1, TIM_OC1, 100); + + /* Reenable outputs. */ + timer_enable_oc_output(TIM1, TIM_OC1); + timer_enable_oc_output(TIM1, TIM_OC1N); + + /* -- OC2 and OC2N configuration -- */ + + /* Disable outputs. */ + timer_disable_oc_output(TIM1, TIM_OC2); + timer_disable_oc_output(TIM1, TIM_OC2N); + + /* Configure global mode of line 2. */ + timer_disable_oc_clear(TIM1, TIM_OC2); + timer_enable_oc_preload(TIM1, TIM_OC2); + timer_set_oc_slow_mode(TIM1, TIM_OC2); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1); + + /* Configure OC2. */ + timer_set_oc_polarity_high(TIM1, TIM_OC2); + timer_set_oc_idle_state_set(TIM1, TIM_OC2); + + /* Configure OC2N. */ + timer_set_oc_polarity_high(TIM1, TIM_OC2N); + timer_set_oc_idle_state_set(TIM1, TIM_OC2N); + + /* Set the capture compare value for OC1. */ + timer_set_oc_value(TIM1, TIM_OC2, 100); + + /* Reenable outputs. */ + timer_enable_oc_output(TIM1, TIM_OC2); + timer_enable_oc_output(TIM1, TIM_OC2N); + + /* -- OC3 and OC3N configuration -- */ + + /* Disable outputs. */ + timer_disable_oc_output(TIM1, TIM_OC3); + timer_disable_oc_output(TIM1, TIM_OC3N); + + /* Configure global mode of line 3. */ + timer_disable_oc_clear(TIM1, TIM_OC3); + timer_enable_oc_preload(TIM1, TIM_OC3); + timer_set_oc_slow_mode(TIM1, TIM_OC3); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1); + + /* Configure OC3. */ + timer_set_oc_polarity_high(TIM1, TIM_OC3); + timer_set_oc_idle_state_set(TIM1, TIM_OC3); + + /* Configure OC3N. */ + timer_set_oc_polarity_high(TIM1, TIM_OC3N); + timer_set_oc_idle_state_set(TIM1, TIM_OC3N); + + /* Set the capture compare value for OC3. */ + timer_set_oc_value(TIM1, TIM_OC3, 100); + + /* Reenable outputs. */ + timer_enable_oc_output(TIM1, TIM_OC3); + timer_enable_oc_output(TIM1, TIM_OC3N); + + /* ---- */ + /* ARR reload enable */ + timer_enable_preload(TIM1); + + /* Enable preload of complementary channel configurations and update on COM event */ + timer_enable_preload_complementry_enable_bits(TIM1); + + /* Enable outputs in the break subsystem */ + timer_enable_break_main_output(TIM1); + + /* Counter enable */ + timer_enable_counter(TIM1); + + /* Enable commutation interrupt */ + timer_enable_irq(TIM1, TIM_DIER_COMIE); +} + +void tim1_trg_com_isr(void) +{ + static int step = 0; + + /* Clear the COM trigger interrupt flag. */ + timer_clear_flag(TIM1, TIM_SR_COMIF); + + /* A simplified and inefficient implementation of PWM On + * scheme. Look at the implementation in Open-BLDC on + * http://open-bldc.org for the proper implementation. This + * one only serves as an example. + * + * Table of the pwm scheme zone configurations when driving: + * @verbatim + * | 1| 2| 3| 4| 5| 6| + * -+--+--+--+--+--+--+ + * A|p+|++| |p-|--| | + * -+--+--+--+--+--+--+ + * B| |p-|--| |p+|++| + * -+--+--+--+--+--+--+ + * C|--| |p+|++| |p-| + * -+--+--+--+--+--+--+ + * | | | | | | '- 360 Deg + * | | | | | '---- 300 Deg + * | | | | '------- 240 Deg + * | | | '---------- 180 Deg + * | | '------------- 120 Deg + * | '---------------- 60 Deg + * '------------------- 0 Deg + * + * Legend: + * p+: PWM on the high side + * p-: PWM on the low side + * --: Low side on + * ++: High side on + * : Floating/NC + * @endverbatim + */ + switch (step) { + case 0: /* A PWM HIGH, B OFF, C LOW */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FROZEN); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FORCE_LOW); + + timer_enable_oc_output(TIM1, TIM_OC1); + timer_disable_oc_output(TIM1, TIM_OC1N); + + timer_disable_oc_output(TIM1, TIM_OC2); + timer_disable_oc_output(TIM1, TIM_OC2N); + + timer_enable_oc_output(TIM1, TIM_OC3); + timer_enable_oc_output(TIM1, TIM_OC3N); + + step++; + break; + case 1: /* A HIGH, B PWM LOW, C OFF */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FORCE_HIGH); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FROZEN); + + timer_enable_oc_output(TIM1, TIM_OC1); + timer_enable_oc_output(TIM1, TIM_OC1N); + + timer_disable_oc_output(TIM1, TIM_OC2); + timer_enable_oc_output(TIM1, TIM_OC2N); + + timer_disable_oc_output(TIM1, TIM_OC3); + timer_disable_oc_output(TIM1, TIM_OC3N); + + step++; + break; + case 2: /* A OFF, B LOW, C PWM HIGH */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FROZEN); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FORCE_LOW); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1); + + timer_disable_oc_output(TIM1, TIM_OC1); + timer_disable_oc_output(TIM1, TIM_OC1N); + + timer_enable_oc_output(TIM1, TIM_OC2); + timer_enable_oc_output(TIM1, TIM_OC2N); + + timer_enable_oc_output(TIM1, TIM_OC3); + timer_disable_oc_output(TIM1, TIM_OC3N); + + step++; + break; + case 3: /* A PWM LOW, B OFF, C HIGH */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_PWM1); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FROZEN); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FORCE_HIGH); + + timer_disable_oc_output(TIM1, TIM_OC1); + timer_enable_oc_output(TIM1, TIM_OC1N); + + timer_disable_oc_output(TIM1, TIM_OC2); + timer_disable_oc_output(TIM1, TIM_OC2N); + + timer_enable_oc_output(TIM1, TIM_OC3); + timer_enable_oc_output(TIM1, TIM_OC3N); + + step++; + break; + case 4: /* A LOW, B PWM HIGH, C OFF */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FORCE_LOW); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_PWM1); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_FROZEN); + + timer_enable_oc_output(TIM1, TIM_OC1); + timer_enable_oc_output(TIM1, TIM_OC1N); + + timer_enable_oc_output(TIM1, TIM_OC2); + timer_disable_oc_output(TIM1, TIM_OC2N); + + timer_disable_oc_output(TIM1, TIM_OC3); + timer_disable_oc_output(TIM1, TIM_OC3N); + + step++; + break; + case 5: /* A OFF, B HIGH, C PWM LOW */ + timer_set_oc_mode(TIM1, TIM_OC1, TIM_OCM_FROZEN); + timer_set_oc_mode(TIM1, TIM_OC2, TIM_OCM_FORCE_HIGH); + timer_set_oc_mode(TIM1, TIM_OC3, TIM_OCM_PWM1); + + timer_disable_oc_output(TIM1, TIM_OC1); + timer_disable_oc_output(TIM1, TIM_OC1N); + + timer_enable_oc_output(TIM1, TIM_OC2); + timer_enable_oc_output(TIM1, TIM_OC2N); + + timer_disable_oc_output(TIM1, TIM_OC3); + timer_enable_oc_output(TIM1, TIM_OC3N); + + step=0; + break; + } + gpio_toggle(GPIOC, GPIO12); +} + +int main(void) +{ + clock_setup(); + gpio_setup(); + tim_setup(); + exti_setup(); + + while (1) { + __asm("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.ld b/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/pwm_6step/pwm_6step.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/spi/Makefile b/examples/stm32f1/stm32-h103/spi/Makefile new file mode 100644 index 0000000..7d3cb72 --- /dev/null +++ b/examples/stm32f1/stm32-h103/spi/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2010 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = spi + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/spi/README b/examples/stm32f1/stm32-h103/spi/README new file mode 100644 index 0000000..d4714c2 --- /dev/null +++ b/examples/stm32f1/stm32-h103/spi/README @@ -0,0 +1,8 @@ +------------------------------------------------------------------------------- +README +------------------------------------------------------------------------------- + +This example program repeatedly sends characters on SPI1 on the ST STM32-based +Olimex STM32-H103 eval board (see http://olimex.com/dev/stm32-h103.html +for details). + diff --git a/examples/stm32f1/stm32-h103/spi/spi.c b/examples/stm32f1/stm32-h103/spi/spi.c new file mode 100644 index 0000000..5a36bb8 --- /dev/null +++ b/examples/stm32f1/stm32-h103/spi/spi.c @@ -0,0 +1,50 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); +} + +void spi_setup(void) +{ + /* TODO */ +} + +void gpio_setup(void) +{ + /* TODO */ +} + +int main(void) +{ + clock_setup(); + gpio_setup(); + spi_setup(); + + while (1) { + spi_write(SPI1, 0xaa); + spi_write(SPI1, 0x55); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/spi/spi.ld b/examples/stm32f1/stm32-h103/spi/spi.ld new file mode 100644 index 0000000..25806f8 --- /dev/null +++ b/examples/stm32f1/stm32-h103/spi/spi.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/timer/Makefile b/examples/stm32f1/stm32-h103/timer/Makefile new file mode 100644 index 0000000..86aced4 --- /dev/null +++ b/examples/stm32f1/stm32-h103/timer/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = timer + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/timer/timer.c b/examples/stm32f1/stm32-h103/timer/timer.c new file mode 100644 index 0000000..ea64c86 --- /dev/null +++ b/examples/stm32f1/stm32-h103/timer/timer.c @@ -0,0 +1,183 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2011 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +u16 frequency_sequence[18] = { + 1000, + 500, + 1000, + 500, + 1000, + 500, + 2000, + 500, + 2000, + 500, + 2000, + 500, + 1000, + 500, + 1000, + 500, + 1000, + 5000 +}; + + +int frequency_sel = 0; + +u16 compare_time; +u16 new_time; +u16 frequency; +int debug = 0; + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + +} + +void gpio_setup(void) +{ + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* + * Set GPIO12 (PORTC) (led) to + * 'output alternate function push-pull'. + */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); + + gpio_set(GPIOC, GPIO12); + +} + +void tim_setup(void) +{ + + /* Enable TIM2 clock. */ + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN); + + + /* Enable TIM2 interrupt. */ + nvic_enable_irq(NVIC_TIM2_IRQ); + + /* Reset TIM2 peripheral */ + timer_reset(TIM2); + + /* Timer global mode: + * - No divider + * - alignment edge + * - direction up + */ + timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, + TIM_CR1_CMS_EDGE, + TIM_CR1_DIR_UP); + + /* Reset prescaler value. */ + timer_set_prescaler(TIM2, 36000); + + /* Enable preload. */ + timer_disable_preload(TIM2); + + /* Continous mode. */ + timer_continuous_mode(TIM2); + + /* Period (36kHz) */ + timer_set_period(TIM2, 65535); + + /* Disable outputs. */ + timer_disable_oc_output(TIM2, TIM_OC1); + timer_disable_oc_output(TIM2, TIM_OC2); + timer_disable_oc_output(TIM2, TIM_OC3); + timer_disable_oc_output(TIM2, TIM_OC4); + + /* -- OC1 configuration -- */ + + /* Configure global mode of line 1. */ + timer_disable_oc_clear(TIM2, TIM_OC1); + timer_disable_oc_preload(TIM2, TIM_OC1); + timer_set_oc_slow_mode(TIM2, TIM_OC1); + timer_set_oc_mode(TIM2, TIM_OC1, TIM_OCM_FROZEN); + + /* Set the capture compare value for OC1. */ + timer_set_oc_value(TIM2, TIM_OC1, 1000); + + /* ---- */ + /* ARR reload enable */ + timer_disable_preload(TIM2); + + /* Counter enable */ + timer_enable_counter(TIM2); + + /* Enable commutation interrupt */ + timer_enable_irq(TIM2, TIM_DIER_CC1IE); +} + +void tim2_isr(void) +{ + + if (timer_get_flag(TIM2, TIM_SR_CC1IF)) { + + /* Clear compare interrupt flag. */ + timer_clear_flag(TIM2, TIM_SR_CC1IF); + + /* + * Get current timer value to calculate next + * compare register value + */ + compare_time = timer_get_counter(TIM2); + + /* + * Calculate and set the next compare value. + */ + frequency = frequency_sequence[frequency_sel++]; + new_time = compare_time + frequency; + + timer_set_oc_value(TIM2, TIM_OC1, + new_time); + if (frequency_sel == 18) { + frequency_sel = 0; + } + + /* Toggle led to indicate compare event */ + gpio_toggle(GPIOC, GPIO12); + + } +} + +int main(void) +{ + + clock_setup(); + gpio_setup(); + tim_setup(); + + while (1) { + __asm("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/timer/timer.ld b/examples/stm32f1/stm32-h103/timer/timer.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/timer/timer.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/traceswo/Makefile b/examples/stm32f1/stm32-h103/traceswo/Makefile new file mode 100644 index 0000000..37510d5 --- /dev/null +++ b/examples/stm32f1/stm32-h103/traceswo/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = traceswo + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/traceswo/README b/examples/stm32f1/stm32-h103/traceswo/README new file mode 100644 index 0000000..34b5227 --- /dev/null +++ b/examples/stm32f1/stm32-h103/traceswo/README @@ -0,0 +1,11 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This experimental program sends some characters on the TRACESWO pin using +the Instrumentation Trace Macrocell (ITM) and Trace Port Interface +Unit (TPIU). + +The SWJ-DP port must be in SWD mode and not JTAG mode for the output +to be visible. + diff --git a/examples/stm32f1/stm32-h103/traceswo/traceswo.c b/examples/stm32f1/stm32-h103/traceswo/traceswo.c new file mode 100644 index 0000000..ac461bb --- /dev/null +++ b/examples/stm32f1/stm32-h103/traceswo/traceswo.c @@ -0,0 +1,100 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include +#include +#include +#include + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); +} + +void trace_setup(void) +{ + /* Enable trace subsystem (we'll use ITM and TPIU) */ + SCS_DEMCR |= SCS_DEMCR_TRCENA; + + /* Use Manchester code for asynchronous transmission */ + TPIU_SPPR = TPIU_SPPR_ASYNC_MANCHESTER; + TPIU_ACPR = 7; + + /* Data width is 1 byte */ + TPIU_CSPSR = TPIU_CSPSR_BYTE; + + /* Formatter and flush control */ + TPIU_FFCR &= ~TPIU_FFCR_ENFCONT; + + /* Enable TRACESWO pin for async mode */ + DBGMCU_CR = DBGMCU_CR_TRACE_IOEN | DBGMCU_CR_TRACE_MODE_ASYNC; + + /* Unlock access to ITM registers */ + /* FIXME: Magic numbers... Is this Cortex-M3 generic? */ + *((volatile uint32_t*)0xE0000FB0) = 0xC5ACCE55; + + /* Enable ITM with ID = 1 */ + ITM_TCR = (1 << 16) | ITM_TCR_ITMENA; + /* Enable stimulus port 1 */ + ITM_TER[0] = 1; + +} + +void gpio_setup(void) +{ + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void trace_send_blocking(char c) +{ + while(!(ITM_STIM[0] & ITM_STIM_FIFOREADY)); + ITM_STIM[0] = c; +} + +int main(void) +{ + int i, j = 0, c = 0; + + clock_setup(); + gpio_setup(); + trace_setup(); + + /* Blink the LED (PC12) on the board with every transmitted byte. */ + while (1) { + gpio_toggle(GPIOC, GPIO12); /* LED on/off */ + trace_send_blocking(c + '0'); + c = (c == 9) ? 0 : c + 1; /* Increment c. */ + if ((j++ % 80) == 0) { /* Newline after line full. */ + trace_send_blocking('\r'); + trace_send_blocking('\n'); + } + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("NOP"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/traceswo/traceswo.ld b/examples/stm32f1/stm32-h103/traceswo/traceswo.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/traceswo/traceswo.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usart/Makefile b/examples/stm32f1/stm32-h103/usart/Makefile new file mode 100644 index 0000000..2c1e1b1 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usart + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usart/README b/examples/stm32f1/stm32-h103/usart/README new file mode 100644 index 0000000..ecd7269 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart/README @@ -0,0 +1,13 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example program sends some characters on USART3 on the ST STM32-based +Olimex STM32-H103 eval board (see http://olimex.com/dev/stm32-h103.html +for details). + +The terminal settings for the receiving device/PC are 38400 8n1. + +The sending is done in a blocking way in the code, see the usart_irq example +for a more elaborate USART example. + diff --git a/examples/stm32f1/stm32-h103/usart/usart.c b/examples/stm32f1/stm32-h103/usart/usart.c new file mode 100644 index 0000000..9692d61 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart/usart.c @@ -0,0 +1,119 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOC clock. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN); + + /* Enable clocks for GPIO port B (for GPIO_USART3_TX) and USART3. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_USART1EN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN | RCC_APB1ENR_USART3EN); +} + +void usart_setup(void) +{ + /* Setup GPIO pin GPIO_USART1_TX. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); + + /* Setup UART parameters. */ + usart_set_baudrate(USART1, 38400); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_mode(USART1, USART_MODE_TX); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + + /* Finally enable the USART. */ + usart_enable(USART1); + + /* Setup GPIO pin GPIO_USART2_TX. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART2_TX); + + /* Setup UART 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); + + /* Setup GPIO pin GPIO_USART3_TX/GPIO10 on GPIO port B for transmit. */ + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART3_TX); + + /* Setup UART parameters. */ + usart_set_baudrate(USART3, 38400); + usart_set_databits(USART3, 8); + usart_set_stopbits(USART3, USART_STOPBITS_1); + usart_set_mode(USART3, USART_MODE_TX); + usart_set_parity(USART3, USART_PARITY_NONE); + usart_set_flow_control(USART3, USART_FLOWCONTROL_NONE); + + /* Finally enable the USART. */ + usart_enable(USART3); +} + +void gpio_setup(void) +{ + /* Set GPIO12 (in GPIO port C) to 'output push-pull'. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +int main(void) +{ + int i, j = 0, c = 0; + + clock_setup(); + gpio_setup(); + usart_setup(); + + /* Blink the LED (PC12) on the board with every transmitted byte. */ + while (1) { + gpio_toggle(GPIOC, GPIO12); /* LED on/off */ + usart_send_blocking(USART1, c + '0'); /* USART1: Send byte. */ + usart_send_blocking(USART2, c + '0'); /* USART2: Send byte. */ + usart_send_blocking(USART3, c + '0'); /* USART3: Send byte. */ + c = (c == 9) ? 0 : c + 1; /* Increment c. */ + if ((j++ % 80) == 0) { /* Newline after line full. */ + usart_send_blocking(USART1, '\r'); + usart_send_blocking(USART1, '\n'); + usart_send_blocking(USART2, '\r'); + usart_send_blocking(USART2, '\n'); + usart_send_blocking(USART3, '\r'); + usart_send_blocking(USART3, '\n'); + } + for (i = 0; i < 800000; i++) /* Wait a bit. */ + __asm__("NOP"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/usart/usart.ld b/examples/stm32f1/stm32-h103/usart/usart.ld new file mode 100644 index 0000000..7ea2b92 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart/usart.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usart_irq/Makefile b/examples/stm32f1/stm32-h103/usart_irq/Makefile new file mode 100644 index 0000000..6ee93bd --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usart_irq + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usart_irq/usart_irq.c b/examples/stm32f1/stm32-h103/usart_irq/usart_irq.c new file mode 100644 index 0000000..9b957dc --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq/usart_irq.c @@ -0,0 +1,119 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOA clock (for LED GPIOs). */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_AFIOEN | + RCC_APB2ENR_USART1EN); +} + +void usart_setup(void) +{ + /* Enable the USART1 interrupt. */ + nvic_enable_irq(NVIC_USART1_IRQ); + + /* Setup GPIO pin GPIO_USART1_RE_TX on GPIO port B for transmit. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); + + /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX); + + /* Setup UART parameters. */ + usart_set_baudrate(USART1, 230400); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_set_mode(USART1, USART_MODE_TX_RX); + + /* Enable USART1 Receive interrupt. */ + USART_CR1(USART1) |= USART_CR1_RXNEIE; + + /* Finally enable the USART. */ + usart_enable(USART1); +} + +void gpio_setup(void) +{ + gpio_set(GPIOC, GPIO12); + + /* Setup GPIO6 and 7 (in GPIO port A) for led use. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void usart1_isr(void) +{ + static u8 data = 'A'; + + /* Check if we were called because of RXNE. */ + if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) && + ((USART_SR(USART1) & USART_SR_RXNE) != 0)) { + + /* Indicate that we got data. */ + gpio_toggle(GPIOC, GPIO12); + + /* Retrieve the data from the peripheral. */ + data = usart_recv(USART1); + + /* Enable transmit interrupt so it sends back the data. */ + USART_CR1(USART1) |= USART_CR1_TXEIE; + } + + /* Check if we were called because of TXE. */ + if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) && + ((USART_SR(USART1) & USART_SR_TXE) != 0)) { + + /* Indicate that we are sending out data. */ + //gpio_toggle(GPIOA, GPIO7); + + /* Put data into the transmit register. */ + usart_send(USART1, data); + + /* Disable the TXE interrupt as we don't need it anymore. */ + USART_CR1(USART1) &= ~USART_CR1_TXEIE; + } +} + +int main(void) +{ + clock_setup(); + gpio_setup(); + usart_setup(); + + /* Wait forever and do nothing. */ + while (1) + __asm__("nop"); + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/usart_irq/usart_irq.ld b/examples/stm32f1/stm32-h103/usart_irq/usart_irq.ld new file mode 100644 index 0000000..7899773 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq/usart_irq.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Open-BLDC (STM32F103CBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usart_irq_printf/Makefile b/examples/stm32f1/stm32-h103/usart_irq_printf/Makefile new file mode 100644 index 0000000..2917a7d --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq_printf/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usart_irq_printf + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.c b/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.c new file mode 100644 index 0000000..42a7472 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.c @@ -0,0 +1,272 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann , + * 2011 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include + +/****************************************************************************** + * Simple ringbuffer implementation from open-bldc's libgovernor that + * you can find at: + * https://github.com/open-bldc/open-bldc/tree/master/source/libgovernor + ******************************************************************************/ + +typedef s32 ring_size_t; + +struct ring { + u8 *data; + ring_size_t size; + u32 begin; + u32 end; +}; + +#define RING_SIZE(RING) ((RING)->size - 1) +#define RING_DATA(RING) (RING)->data +#define RING_EMPTY(RING) ((RING)->begin == (RING)->end) + +void ring_init(struct ring *ring, u8 * buf, ring_size_t size) +{ + ring->data = buf; + ring->size = size; + ring->begin = 0; + ring->end = 0; +} + +s32 ring_write_ch(struct ring *ring, u8 ch) +{ + if (((ring->end + 1) % ring->size) != ring->begin) { + ring->data[ring->end++] = ch; + ring->end %= ring->size; + return (u32) ch; + } + + return -1; +} + +s32 ring_write(struct ring * ring, u8 * data, ring_size_t size) +{ + s32 i; + + for (i = 0; i < size; i++) { + if (ring_write_ch(ring, data[i]) < 0) { + return -i; + } + } + + return i; +} + +s32 ring_read_ch(struct ring * ring, u8 * ch) +{ + s32 ret = -1; + + if (ring->begin != ring->end) { + ret = ring->data[ring->begin++]; + ring->begin %= ring->size; + if (ch) + *ch = ret; + } + + return ret; +} + +s32 ring_read(struct ring * ring, u8 * data, ring_size_t size) +{ + s32 i; + + for (i = 0; i < size; i++) { + if (ring_read_ch(ring, data + i) < 0) { + return i; + } + } + + return -i; +} + +/****************************************************************************** + * The example implementation + ******************************************************************************/ + +#define BUFFER_SIZE 1024 + +struct ring output_ring; +u8 output_ring_buffer[BUFFER_SIZE]; + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOA clock (for LED GPIOs). */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_AFIOEN | + RCC_APB2ENR_USART1EN); +} + +void usart_setup(void) +{ + + /* Initialize output ring buffer */ + ring_init(&output_ring, output_ring_buffer, BUFFER_SIZE); + + /* Enable the USART1 interrupt. */ + nvic_enable_irq(NVIC_USART1_IRQ); + + /* Setup GPIO pin GPIO_USART1_RE_TX on GPIO port B for transmit. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); + + /* Setup GPIO pin GPIO_USART1_RE_RX on GPIO port B for receive. */ + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, GPIO_USART1_RX); + + /* Setup UART parameters. */ + usart_set_baudrate(USART1, 230400); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_set_mode(USART1, USART_MODE_TX_RX); + + /* Enable USART1 Receive interrupt. */ + USART_CR1(USART1) |= USART_CR1_RXNEIE; + + /* Finally enable the USART. */ + usart_enable(USART1); +} + +void gpio_setup(void) +{ + gpio_set(GPIOC, GPIO12); + + /* Setup GPIO6 and 7 (in GPIO port A) for led use. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +void usart1_isr(void) +{ + /* Check if we were called because of RXNE. */ + if (((USART_CR1(USART1) & USART_CR1_RXNEIE) != 0) && + ((USART_SR(USART1) & USART_SR_RXNE) != 0)) { + + /* Indicate that we got data. */ + gpio_toggle(GPIOC, GPIO12); + + /* Retrieve the data from the peripheral. */ + ring_write_ch(&output_ring, usart_recv(USART1)); + + /* Enable transmit interrupt so it sends back the data. */ + USART_CR1(USART1) |= USART_CR1_TXEIE; + } + + /* Check if we were called because of TXE. */ + if (((USART_CR1(USART1) & USART_CR1_TXEIE) != 0) && + ((USART_SR(USART1) & USART_SR_TXE) != 0)) { + + s32 data; + + data = ring_read_ch(&output_ring, NULL); + + if (data == -1) { + /* Disable the TXE interrupt as we don't need it anymore. */ + USART_CR1(USART1) &= ~USART_CR1_TXEIE; + } else { + /* Put data into the transmit register. */ + usart_send(USART1, data); + } + } +} + +int _write (int file, char *ptr, int len) +{ + int ret; + + if (file == 1) { + ret = ring_write(&output_ring, (u8 *)ptr, len); + + if (ret < 0) ret = -ret; + + USART_CR1(USART1) |= USART_CR1_TXEIE; + + return ret; + } + + errno = EIO; + return -1; +} + +void systick_setup(void) { + + /* 72MHz / 8 => 9000000 counts per second */ + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + + /* 9000000/9000 = 1000 overflows per second - every 1ms one interrupt */ + systick_set_reload(9000); + + systick_interrupt_enable(); + + /* Start counting. */ + systick_counter_enable(); + +} + +void sys_tick_handler(void) +{ + static int counter = 0; + static float fcounter = 0.0; + static double dcounter = 0.0; + + static u32 temp32 = 0; + + temp32++; + + /* We call this handler every 1ms so we are sending hello world every 10ms / 100Hz. */ + if (temp32 == 10) { + printf("Hello World! %i %f %f\r\n", counter, fcounter, dcounter); + counter++; + fcounter+=0.01; + dcounter+=0.01; + + temp32 = 0; + } +} + +int main(void) +{ + + clock_setup(); + gpio_setup(); + usart_setup(); + systick_setup(); + + while (1) { + __asm__("nop"); + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.ld b/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.ld new file mode 100644 index 0000000..7899773 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_irq_printf/usart_irq_printf.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Open-BLDC (STM32F103CBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usart_printf/Makefile b/examples/stm32f1/stm32-h103/usart_printf/Makefile new file mode 100644 index 0000000..fb26208 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_printf/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usart_printf + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usart_printf/usart_printf.c b/examples/stm32f1/stm32-h103/usart_printf/usart_printf.c new file mode 100644 index 0000000..26fcee6 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_printf/usart_printf.c @@ -0,0 +1,108 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann , + * 2011 Piotr Esden-Tempski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include + +#include +#include + +void clock_setup(void) +{ + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + /* Enable GPIOA clock (for LED GPIOs). */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + /* Enable clocks for GPIO port A (for GPIO_USART1_TX) and USART1. */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN | + RCC_APB2ENR_AFIOEN | + RCC_APB2ENR_USART1EN); +} + +void usart_setup(void) +{ + /* Setup GPIO pin GPIO_USART1_RE_TX on GPIO port B for transmit. */ + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); + + /* Setup UART parameters. */ + usart_set_baudrate(USART1, 230400); + usart_set_databits(USART1, 8); + usart_set_stopbits(USART1, USART_STOPBITS_1); + usart_set_parity(USART1, USART_PARITY_NONE); + usart_set_flow_control(USART1, USART_FLOWCONTROL_NONE); + usart_set_mode(USART1, USART_MODE_TX); + + /* Finally enable the USART. */ + usart_enable(USART1); +} + +void gpio_setup(void) +{ + gpio_set(GPIOC, GPIO12); + + /* Setup GPIO6 and 7 (in GPIO port A) for led use. */ + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); +} + +int _write (int file, char *ptr, int len) +{ + int i; + + if (file == 1) { + for (i = 0; i < len; i++){ + usart_send_blocking(USART1, ptr[i]); + } + + return i; + } + + errno = EIO; + return -1; +} + +int main(void) +{ + int counter = 0; + float fcounter = 0.0; + double dcounter = 0.0; + + clock_setup(); + gpio_setup(); + usart_setup(); + + /* + * Write Hello World an integer, float and double all over + * again while incrementing the numbers. + */ + while (1) { + gpio_toggle(GPIOC, GPIO12); + printf("Hello World! %i %f %f\r\n", counter, fcounter, dcounter); + counter++; + fcounter+=0.01; + dcounter+=0.01; + } + + return 0; +} diff --git a/examples/stm32f1/stm32-h103/usart_printf/usart_printf.ld b/examples/stm32f1/stm32-h103/usart_printf/usart_printf.ld new file mode 100644 index 0000000..7899773 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usart_printf/usart_printf.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Open-BLDC (STM32F103CBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usb_cdcacm/Makefile b/examples/stm32f1/stm32-h103/usb_cdcacm/Makefile new file mode 100644 index 0000000..38179e3 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_cdcacm/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = cdcacm + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usb_cdcacm/README b/examples/stm32f1/stm32-h103/usb_cdcacm/README new file mode 100644 index 0000000..2f1ee4b --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_cdcacm/README @@ -0,0 +1,7 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example implements a USB CDC-ACM device (aka Virtual Serial Port) +to demonstrate the use of the USB device stack. + diff --git a/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.c b/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.c new file mode 100644 index 0000000..4b90640 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.c @@ -0,0 +1,246 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = USB_CLASS_CDC, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0x5740, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +/* This notification endpoint isn't implemented. According to CDC spec its + * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm + * driver. */ +static const struct usb_endpoint_descriptor comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x83, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 1, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 0, + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 0, + .bSubordinateInterface0 = 1, + } +}; + +static const struct usb_interface_descriptor comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 0, + + .endpoint = comm_endp, + + .extra = &cdcacm_functional_descriptors, + .extralen = sizeof(cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = data_endp, +}}; + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = comm_iface, +}, { + .num_altsetting = 1, + .altsetting = data_iface, +}}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 2, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "x", + "Black Sphere Technologies", + "CDC-ACM Demo", + "DEMO" +}; + +static int cdcacm_control_request(struct usb_setup_data *req, u8 **buf, + u16 *len, void (**complete)(struct usb_setup_data *req)) +{ + (void)complete; + (void)buf; + + switch(req->bRequest) { + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: { + /* This Linux cdc_acm driver requires this to be implemented + * even though it's optional in the CDC spec, and we don't + * advertise it in the ACM functional descriptor. */ + char buf[10]; + struct usb_cdc_notification *notif = (void*)buf; + + /* We echo signals back to host as notification */ + notif->bmRequestType = 0xA1; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wValue = 0; + notif->wIndex = 0; + notif->wLength = 2; + buf[8] = req->wValue & 3; + buf[9] = 0; + //usbd_ep_write_packet(0x83, buf, 10); + return 1; + } + case USB_CDC_REQ_SET_LINE_CODING: + if(*len < sizeof(struct usb_cdc_line_coding)) + return 0; + + return 1; + } + return 0; +} + +static void cdcacm_data_rx_cb(u8 ep) +{ + (void)ep; + + char buf[64]; + int len = usbd_ep_read_packet(0x01, buf, 64); + if(len) { + usbd_ep_write_packet(0x82, buf, len); + buf[len] = 0; + } +} + +static void cdcacm_set_config(u16 wValue) +{ + (void)wValue; + + usbd_ep_setup(0x01, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb); + usbd_ep_setup(0x82, USB_ENDPOINT_ATTR_BULK, 64, NULL); + usbd_ep_setup(0x83, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + + usbd_register_control_callback( + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + cdcacm_control_request); +} + +int main(void) +{ + int i; + + rcc_clock_setup_in_hsi_out_48mhz(); + + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + gpio_set(GPIOC, GPIO11); + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); + + usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); + usbd_register_set_config_callback(cdcacm_set_config); + + for (i = 0; i < 0x800000; i++) + __asm__("nop"); + gpio_clear(GPIOC, GPIO11); + + while (1) + usbd_poll(); +} diff --git a/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.ld b/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.ld new file mode 100644 index 0000000..928c898 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_cdcacm/cdcacm.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usb_dfu/Makefile b/examples/stm32f1/stm32-h103/usb_dfu/Makefile new file mode 100644 index 0000000..48e2d6b --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_dfu/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usbdfu + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usb_dfu/README b/examples/stm32f1/stm32-h103/usb_dfu/README new file mode 100644 index 0000000..9c0169a --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_dfu/README @@ -0,0 +1,7 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example implements a USB Device Firmware Upgrade (DFU) bootloader +to demonstrate the use of the USB device stack. + diff --git a/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.c b/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.c new file mode 100644 index 0000000..7ffbc74 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.c @@ -0,0 +1,270 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define APP_ADDRESS 0x08002000 + +/* Commands sent with wBlockNum == 0 as per ST implementation. */ +#define CMD_SETADDR 0x21 +#define CMD_ERASE 0x41 + +/* We need a special large control buffer for this device: */ +u8 usbd_control_buffer[1024]; + +static enum dfu_state usbdfu_state = STATE_DFU_IDLE; + +static struct { + u8 buf[sizeof(usbd_control_buffer)]; + u16 len; + u32 addr; + u16 blocknum; +} prog; + +const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0xDF11, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, /* Device Firmware Upgrade */ + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 2, + + /* The ST Microelectronics DfuSe application needs this string. + * The format isn't documented... */ + .iInterface = 4, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + +const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = &iface, +}}; + +const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "x", + "Black Sphere Technologies", + "DFU Demo", + "DEMO", + /* This string is used by ST Microelectronics' DfuSe utility */ + "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +}; + +static u8 usbdfu_getstatus(u32 *bwPollTimeout) +{ + switch(usbdfu_state) { + case STATE_DFU_DNLOAD_SYNC: + usbdfu_state = STATE_DFU_DNBUSY; + *bwPollTimeout = 100; + return DFU_STATUS_OK; + + case STATE_DFU_MANIFEST_SYNC: + /* Device will reset when read is complete */ + usbdfu_state = STATE_DFU_MANIFEST; + return DFU_STATUS_OK; + + default: + return DFU_STATUS_OK; + } +} + +static void usbdfu_getstatus_complete(struct usb_setup_data *req) +{ + int i; + (void)req; + + switch(usbdfu_state) { + case STATE_DFU_DNBUSY: + + flash_unlock(); + if(prog.blocknum == 0) { + switch(prog.buf[0]) { + case CMD_ERASE: + flash_erase_page(*(u32*)(prog.buf+1)); + case CMD_SETADDR: + prog.addr = *(u32*)(prog.buf+1); + } + } else { + u32 baseaddr = prog.addr + + ((prog.blocknum - 2) * + dfu_function.wTransferSize); + for(i = 0; i < prog.len; i += 2) + flash_program_half_word(baseaddr + i, + *(u16*)(prog.buf+i)); + } + flash_lock(); + + /* We jump straight to dfuDNLOAD-IDLE, + * skipping dfuDNLOAD-SYNC + */ + usbdfu_state = STATE_DFU_DNLOAD_IDLE; + return; + + case STATE_DFU_MANIFEST: + /* USB device must detach, we just reset... */ + scb_reset_system(); + return; /* Will never return */ + default: + return; + } +} + +static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, + u16 *len, void (**complete)(struct usb_setup_data *req)) +{ + + if((req->bmRequestType & 0x7F) != 0x21) + return 0; /* Only accept class request */ + + switch(req->bRequest) { + case DFU_DNLOAD: + if((len == NULL) || (*len == 0)) { + usbdfu_state = STATE_DFU_MANIFEST_SYNC; + return 1; + } else { + /* Copy download data for use on GET_STATUS */ + prog.blocknum = req->wValue; + prog.len = *len; + memcpy(prog.buf, *buf, *len); + usbdfu_state = STATE_DFU_DNLOAD_SYNC; + return 1; + } + case DFU_CLRSTATUS: + /* Clear error and return to dfuIDLE */ + if(usbdfu_state == STATE_DFU_ERROR) + usbdfu_state = STATE_DFU_IDLE; + return 1; + case DFU_ABORT: + /* Abort returns to dfuIDLE state */ + usbdfu_state = STATE_DFU_IDLE; + return 1; + case DFU_UPLOAD: + /* Upload not supported for now */ + return 0; + case DFU_GETSTATUS: { + u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ + + (*buf)[0] = usbdfu_getstatus(&bwPollTimeout); + (*buf)[1] = bwPollTimeout & 0xFF; + (*buf)[2] = (bwPollTimeout >> 8) & 0xFF; + (*buf)[3] = (bwPollTimeout >> 16) & 0xFF; + (*buf)[4] = usbdfu_state; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + *complete = usbdfu_getstatus_complete; + + return 1; + } + case DFU_GETSTATE: + /* Return state with no state transision */ + *buf[0] = usbdfu_state; + *len = 1; + return 1; + } + + return 0; +} + +int main(void) +{ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + if(!gpio_get(GPIOA, GPIO10)) { + /* Boot the application if it's valid */ + if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { + /* Set vector table base address */ + SCB_VTOR = APP_ADDRESS & 0xFFFF; + /* Initialise master stack pointer */ + asm volatile ("msr msp, %0"::"g" + (*(volatile u32*)APP_ADDRESS)); + /* Jump to application */ + (*(void(**)())(APP_ADDRESS + 4))(); + } + } + + rcc_clock_setup_in_hsi_out_48mhz(); + + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); + + usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); + usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); + usbd_register_control_callback( + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + usbdfu_control_request); + + gpio_set(GPIOA, GPIO15); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); + + while (1) + usbd_poll(); +} diff --git a/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.ld b/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.ld new file mode 100644 index 0000000..54e5dac --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_dfu/usbdfu.ld @@ -0,0 +1,29 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 8K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 4K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usb_hid/Makefile b/examples/stm32f1/stm32-h103/usb_hid/Makefile new file mode 100644 index 0000000..d831e9e --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_hid/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usbhid + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usb_hid/README b/examples/stm32f1/stm32-h103/usb_hid/README new file mode 100644 index 0000000..48a9b39 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_hid/README @@ -0,0 +1,7 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example implements a USB Human Interface Device (HID) +to demonstrate the use of the USB device stack. + diff --git a/examples/stm32f1/stm32-h103/usb_hid/usbhid.c b/examples/stm32f1/stm32-h103/usb_hid/usbhid.c new file mode 100644 index 0000000..a21fce6 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_hid/usbhid.c @@ -0,0 +1,272 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +/* Define this to include the DFU APP interface. */ +#define INCLUDE_DFU_INTERFACE + +#ifdef INCLUDE_DFU_INTERFACE +#include +#include +#endif + +const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0x5710, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +/* I have no idea what this means. I haven't read the HID spec. */ +static const u8 hid_report_descriptor[] = { + 0x05, 0x01, 0x09, 0x02, 0xA1, 0x01, 0x09, 0x01, + 0xA1, 0x00, 0x05, 0x09, 0x19, 0x01, 0x29, 0x03, + 0x15, 0x00, 0x25, 0x01, 0x95, 0x03, 0x75, 0x01, + 0x81, 0x02, 0x95, 0x01, 0x75, 0x05, 0x81, 0x01, + 0x05, 0x01, 0x09, 0x30, 0x09, 0x31, 0x09, 0x38, + 0x15, 0x81, 0x25, 0x7F, 0x75, 0x08, 0x95, 0x03, + 0x81, 0x06, 0xC0, 0x09, 0x3c, 0x05, 0xff, 0x09, + 0x01, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, + 0x02, 0xb1, 0x22, 0x75, 0x06, 0x95, 0x01, 0xb1, + 0x01, 0xc0 +}; + +static const struct { + struct usb_hid_descriptor hid_descriptor; + struct { + u8 bReportDescriptorType; + u16 wDescriptorLength; + } __attribute__((packed)) hid_report; +} __attribute__((packed)) hid_function = { + .hid_descriptor = { + .bLength = sizeof(hid_function), + .bDescriptorType = USB_DT_HID, + .bcdHID = 0x0100, + .bCountryCode = 0, + .bNumDescriptors = 1, + }, + .hid_report = { + .bReportDescriptorType = USB_DT_REPORT, + .wDescriptorLength = sizeof(hid_report_descriptor), + } +}; + +const struct usb_endpoint_descriptor hid_endpoint = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 4, + .bInterval = 0x20, +}; + +const struct usb_interface_descriptor hid_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_HID, + .bInterfaceSubClass = 1, /* boot */ + .bInterfaceProtocol = 2, /* mouse */ + .iInterface = 0, + + .endpoint = &hid_endpoint, + + .extra = &hid_function, + .extralen = sizeof(hid_function), +}; + +#ifdef INCLUDE_DFU_INTERFACE +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor dfu_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 0, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; +#endif + +const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = &hid_iface, +#ifdef INCLUDE_DFU_INTERFACE +}, { + .num_altsetting = 1, + .altsetting = &dfu_iface, +#endif +}}; + +const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, +#ifdef INCLUDE_DFU_INTERFACE + .bNumInterfaces = 2, +#else + .bNumInterfaces = 1, +#endif + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "x", + "Black Sphere Technologies", + "HID Demo", + "DEMO", +}; + +static int hid_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, + void (**complete)(struct usb_setup_data *req)) +{ + (void)complete; + + if((req->bmRequestType != 0x81) || + (req->bRequest != USB_REQ_GET_DESCRIPTOR) || + (req->wValue != 0x2200)) + return 0; + + /* Handle the HID report descriptor */ + *buf = (u8*)hid_report_descriptor; + *len = sizeof(hid_report_descriptor); + + return 1; +} + +#ifdef INCLUDE_DFU_INTERFACE +static void dfu_detach_complete(struct usb_setup_data *req) +{ + (void)req; + + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO10); + gpio_set(GPIOA, GPIO10); + scb_reset_core(); +} + +static int dfu_control_request(struct usb_setup_data *req, u8 **buf, u16 *len, + void (**complete)(struct usb_setup_data *req)) +{ + (void)buf; + (void)len; + + if((req->bmRequestType != 0x21) || (req->bRequest != DFU_DETACH)) + return 0; /* Only accept class request */ + + *complete = dfu_detach_complete; + + return 1; +} +#endif + +static void hid_set_config(u16 wValue) +{ + (void)wValue; + + usbd_ep_setup(0x81, USB_ENDPOINT_ATTR_INTERRUPT, 4, NULL); + + usbd_register_control_callback( + USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + hid_control_request); +#ifdef INCLUDE_DFU_INTERFACE + usbd_register_control_callback( + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + dfu_control_request); +#endif + + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(100000); + systick_interrupt_enable(); + systick_counter_enable(); +} + +int main(void) +{ + rcc_clock_setup_in_hsi_out_48mhz(); + + + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + + gpio_set(GPIOC, GPIO11); + gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO11); + + usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); + usbd_register_set_config_callback(hid_set_config); + + {int i; for (i=0;i<0x80000;i++);} + gpio_clear(GPIOC, GPIO11); + + while (1) + usbd_poll(); +} + +void sys_tick_handler(void) +{ + static int x = 0; + static int dir = 1; + u8 buf[4] = {0, 0, 0, 0}; + + buf[1] = dir; + x += dir; + if(x > 30) dir = -dir; + if(x < -30) dir = -dir; + + usbd_ep_write_packet(0x81, buf, 4); +} diff --git a/examples/stm32f1/stm32-h103/usb_hid/usbhid.ld b/examples/stm32f1/stm32-h103/usb_hid/usbhid.ld new file mode 100644 index 0000000..928c898 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_hid/usbhid.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + diff --git a/examples/stm32f1/stm32-h103/usb_iap/Makefile b/examples/stm32f1/stm32-h103/usb_iap/Makefile new file mode 100644 index 0000000..bed9908 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_iap/Makefile @@ -0,0 +1,23 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2009 Uwe Hermann +## +## This program is free software: you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . +## + +BINARY = usbiap + +include ../../Makefile.include + diff --git a/examples/stm32f1/stm32-h103/usb_iap/README b/examples/stm32f1/stm32-h103/usb_iap/README new file mode 100644 index 0000000..2966684 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_iap/README @@ -0,0 +1,8 @@ +------------------------------------------------------------------------------ +README +------------------------------------------------------------------------------ + +This example implements a USB bootloader for the Paparazzi project. + +TODO: Move to examples/lisa-m? + diff --git a/examples/stm32f1/stm32-h103/usb_iap/usbiap.c b/examples/stm32f1/stm32-h103/usb_iap/usbiap.c new file mode 100644 index 0000000..7ffbc74 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_iap/usbiap.c @@ -0,0 +1,270 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define APP_ADDRESS 0x08002000 + +/* Commands sent with wBlockNum == 0 as per ST implementation. */ +#define CMD_SETADDR 0x21 +#define CMD_ERASE 0x41 + +/* We need a special large control buffer for this device: */ +u8 usbd_control_buffer[1024]; + +static enum dfu_state usbdfu_state = STATE_DFU_IDLE; + +static struct { + u8 buf[sizeof(usbd_control_buffer)]; + u16 len; + u32 addr; + u16 blocknum; +} prog; + +const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x0483, + .idProduct = 0xDF11, + .bcdDevice = 0x0200, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, /* Device Firmware Upgrade */ + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 2, + + /* The ST Microelectronics DfuSe application needs this string. + * The format isn't documented... */ + .iInterface = 4, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + +const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .altsetting = &iface, +}}; + +const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0xC0, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +static const char *usb_strings[] = { + "x", + "Black Sphere Technologies", + "DFU Demo", + "DEMO", + /* This string is used by ST Microelectronics' DfuSe utility */ + "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +}; + +static u8 usbdfu_getstatus(u32 *bwPollTimeout) +{ + switch(usbdfu_state) { + case STATE_DFU_DNLOAD_SYNC: + usbdfu_state = STATE_DFU_DNBUSY; + *bwPollTimeout = 100; + return DFU_STATUS_OK; + + case STATE_DFU_MANIFEST_SYNC: + /* Device will reset when read is complete */ + usbdfu_state = STATE_DFU_MANIFEST; + return DFU_STATUS_OK; + + default: + return DFU_STATUS_OK; + } +} + +static void usbdfu_getstatus_complete(struct usb_setup_data *req) +{ + int i; + (void)req; + + switch(usbdfu_state) { + case STATE_DFU_DNBUSY: + + flash_unlock(); + if(prog.blocknum == 0) { + switch(prog.buf[0]) { + case CMD_ERASE: + flash_erase_page(*(u32*)(prog.buf+1)); + case CMD_SETADDR: + prog.addr = *(u32*)(prog.buf+1); + } + } else { + u32 baseaddr = prog.addr + + ((prog.blocknum - 2) * + dfu_function.wTransferSize); + for(i = 0; i < prog.len; i += 2) + flash_program_half_word(baseaddr + i, + *(u16*)(prog.buf+i)); + } + flash_lock(); + + /* We jump straight to dfuDNLOAD-IDLE, + * skipping dfuDNLOAD-SYNC + */ + usbdfu_state = STATE_DFU_DNLOAD_IDLE; + return; + + case STATE_DFU_MANIFEST: + /* USB device must detach, we just reset... */ + scb_reset_system(); + return; /* Will never return */ + default: + return; + } +} + +static int usbdfu_control_request(struct usb_setup_data *req, u8 **buf, + u16 *len, void (**complete)(struct usb_setup_data *req)) +{ + + if((req->bmRequestType & 0x7F) != 0x21) + return 0; /* Only accept class request */ + + switch(req->bRequest) { + case DFU_DNLOAD: + if((len == NULL) || (*len == 0)) { + usbdfu_state = STATE_DFU_MANIFEST_SYNC; + return 1; + } else { + /* Copy download data for use on GET_STATUS */ + prog.blocknum = req->wValue; + prog.len = *len; + memcpy(prog.buf, *buf, *len); + usbdfu_state = STATE_DFU_DNLOAD_SYNC; + return 1; + } + case DFU_CLRSTATUS: + /* Clear error and return to dfuIDLE */ + if(usbdfu_state == STATE_DFU_ERROR) + usbdfu_state = STATE_DFU_IDLE; + return 1; + case DFU_ABORT: + /* Abort returns to dfuIDLE state */ + usbdfu_state = STATE_DFU_IDLE; + return 1; + case DFU_UPLOAD: + /* Upload not supported for now */ + return 0; + case DFU_GETSTATUS: { + u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ + + (*buf)[0] = usbdfu_getstatus(&bwPollTimeout); + (*buf)[1] = bwPollTimeout & 0xFF; + (*buf)[2] = (bwPollTimeout >> 8) & 0xFF; + (*buf)[3] = (bwPollTimeout >> 16) & 0xFF; + (*buf)[4] = usbdfu_state; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + *complete = usbdfu_getstatus_complete; + + return 1; + } + case DFU_GETSTATE: + /* Return state with no state transision */ + *buf[0] = usbdfu_state; + *len = 1; + return 1; + } + + return 0; +} + +int main(void) +{ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + if(!gpio_get(GPIOA, GPIO10)) { + /* Boot the application if it's valid */ + if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { + /* Set vector table base address */ + SCB_VTOR = APP_ADDRESS & 0xFFFF; + /* Initialise master stack pointer */ + asm volatile ("msr msp, %0"::"g" + (*(volatile u32*)APP_ADDRESS)); + /* Jump to application */ + (*(void(**)())(APP_ADDRESS + 4))(); + } + } + + rcc_clock_setup_in_hsi_out_48mhz(); + + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + + AFIO_MAPR |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON; + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO15); + + usbd_init(&stm32f103_usb_driver, &dev, &config, usb_strings); + usbd_set_control_buffer_size(sizeof(usbd_control_buffer)); + usbd_register_control_callback( + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + usbdfu_control_request); + + gpio_set(GPIOA, GPIO15); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO15); + + while (1) + usbd_poll(); +} diff --git a/examples/stm32f1/stm32-h103/usb_iap/usbiap.ld b/examples/stm32f1/stm32-h103/usb_iap/usbiap.ld new file mode 100644 index 0000000..928c898 --- /dev/null +++ b/examples/stm32f1/stm32-h103/usb_iap/usbiap.ld @@ -0,0 +1,31 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Thomas Otto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K +} + +/* Include the common ld script. */ +INCLUDE libopencm3_stm32.ld + -- cgit v1.2.3