From 6e72fb26efbb45f1244d95d33d459566a8af57fe Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 14 Aug 2015 17:09:27 +0200 Subject: ucoo/{intf,hal/exti,arch}: add EXTI --- ucoo/arch/arch.stm32f1.cc | 1 + ucoo/arch/arch.stm32f4.cc | 1 + ucoo/hal/exti/Module | 1 + ucoo/hal/exti/exti.hh | 33 ++++ ucoo/hal/exti/exti.stm32.cc | 295 ++++++++++++++++++++++++++++++++++ ucoo/hal/exti/exti.stm32.hh | 86 ++++++++++ ucoo/hal/exti/test/Makefile | 9 ++ ucoo/hal/exti/test/test_exti.stm32.cc | 66 ++++++++ ucoo/intf/exti.hh | 56 +++++++ 9 files changed, 548 insertions(+) create mode 100644 ucoo/hal/exti/Module create mode 100644 ucoo/hal/exti/exti.hh create mode 100644 ucoo/hal/exti/exti.stm32.cc create mode 100644 ucoo/hal/exti/exti.stm32.hh create mode 100644 ucoo/hal/exti/test/Makefile create mode 100644 ucoo/hal/exti/test/test_exti.stm32.cc create mode 100644 ucoo/intf/exti.hh (limited to 'ucoo') diff --git a/ucoo/arch/arch.stm32f1.cc b/ucoo/arch/arch.stm32f1.cc index 090e2c1..a2d659c 100644 --- a/ucoo/arch/arch.stm32f1.cc +++ b/ucoo/arch/arch.stm32f1.cc @@ -32,6 +32,7 @@ void arch_init (int argc, const char **argv) { rcc_clock_setup_in_hse_12mhz_out_72mhz (); + rcc_periph_clock_enable (RCC_AFIO); } } // namespace ucoo diff --git a/ucoo/arch/arch.stm32f4.cc b/ucoo/arch/arch.stm32f4.cc index c3e7dc2..74c7306 100644 --- a/ucoo/arch/arch.stm32f4.cc +++ b/ucoo/arch/arch.stm32f4.cc @@ -33,6 +33,7 @@ arch_init (int argc, const char **argv) { rcc_clock_setup_hse_3v3 (&hse_8mhz_3v3[CLOCK_3V3_120MHZ]); rcc_ahb_frequency = 120000000; + rcc_periph_clock_enable (RCC_SYSCFG); } } // namespace ucoo diff --git a/ucoo/hal/exti/Module b/ucoo/hal/exti/Module new file mode 100644 index 0000000..c4c8a06 --- /dev/null +++ b/ucoo/hal/exti/Module @@ -0,0 +1 @@ +ucoo_hal_exti_SOURCES := exti.stm32.cc diff --git a/ucoo/hal/exti/exti.hh b/ucoo/hal/exti/exti.hh new file mode 100644 index 0000000..5aa0c4f --- /dev/null +++ b/ucoo/hal/exti/exti.hh @@ -0,0 +1,33 @@ +#ifndef ucoo_hal_exti_exti_hh +#define ucoo_hal_exti_exti_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2015 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} + +#if defined TARGET_stm32 +# include "exti.stm32.hh" +#else +# error "not implemented for this target" +#endif + +#endif // ucoo_hal_exti_exti_hh diff --git a/ucoo/hal/exti/exti.stm32.cc b/ucoo/hal/exti/exti.stm32.cc new file mode 100644 index 0000000..120b25e --- /dev/null +++ b/ucoo/hal/exti/exti.stm32.cc @@ -0,0 +1,295 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2015 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/hal/exti/exti.stm32.hh" +#include "ucoo/common.hh" + +#include +#include +#if !defined AFIO_BASE +# include +#endif + +namespace ucoo { + +/// Information on EXTI hardware structure. +struct exti_hardware_t +{ + /// Corresponding IRQ. + int irq; + /// Pointer to number of enabled EXTI for shared vectors, or NULL. + int *enabled; +}; + +/// Number of enabled EXTI for vector 9 down to 5. +static int exti_vector_9_5_enabled; + +/// Number of enabled EXTI for vector 15 down to 10. +static int exti_vector_15_10_enabled; + +/// Information on EXTI hardware array. +struct exti_hardware_t exti_hardware[] = +{ + { NVIC_EXTI0_IRQ, nullptr }, + { NVIC_EXTI1_IRQ, nullptr }, + { NVIC_EXTI2_IRQ, nullptr }, + { NVIC_EXTI3_IRQ, nullptr }, + { NVIC_EXTI4_IRQ, nullptr }, + { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled }, + { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled }, + { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled }, + { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled }, + { NVIC_EXTI9_5_IRQ, &exti_vector_9_5_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, + { NVIC_EXTI15_10_IRQ, &exti_vector_15_10_enabled }, +}; + +static ExtiHard *exti_instances[lengthof (exti_hardware)]; + +} // namespace ucoo + +extern "C" { + +// If the interrupt is triggered again after being cleared, the interrupt +// handler will be reentered. There is no need to loop. + +void +exti0_isr () +{ + EXTI_PR = 1u << 0; + assert (ucoo::exti_instances[0]); + ucoo::exti_instances[0]->isr (); +} + +void +exti1_isr () +{ + EXTI_PR = 1u << 1; + assert (ucoo::exti_instances[1]); + ucoo::exti_instances[1]->isr (); +} + +void +exti2_isr () +{ + EXTI_PR = 1u << 2; + assert (ucoo::exti_instances[2]); + ucoo::exti_instances[2]->isr (); +} + +void +exti3_isr () +{ + EXTI_PR = 1u << 3; + assert (ucoo::exti_instances[3]); + ucoo::exti_instances[3]->isr (); +} + +void +exti4_isr () +{ + EXTI_PR = 1u << 4; + assert (ucoo::exti_instances[4]); + ucoo::exti_instances[4]->isr (); +} + +void +exti9_5_isr () +{ + uint32_t pending = EXTI_PR & 0x3e0; + EXTI_PR = pending; + for (int i = 5; i <= 9; i++) + { + if (pending & (1u << i)) + { + assert (ucoo::exti_instances[i]); + ucoo::exti_instances[i]->isr (); + } + } +} + +void +exti15_10_isr () +{ + uint32_t pending = EXTI_PR & 0xfc00; + EXTI_PR = pending; + for (int i = 10; i <= 15; i++) + { + if (pending & (1u << i)) + { + assert (ucoo::exti_instances[i]); + ucoo::exti_instances[i]->isr (); + } + } +} + +} + +namespace ucoo { + +ExtiHard::ExtiHard (int n) + : n_ (n) +{ + assert (n < lengthof (exti_instances)); + assert (!exti_instances[n]); + exti_instances[n] = this; +} + +ExtiHard::~ExtiHard () +{ + disable (); + exti_instances[n_] = 0; +} + +void +ExtiHard::enable () +{ + assert (handler_); + EXTI_IMR |= 1u << n_; + if (exti_hardware[n_].enabled) + { + if (!(*exti_hardware[n_].enabled)++) + nvic_enable_irq (exti_hardware[n_].irq); + } + else + nvic_enable_irq (exti_hardware[n_].irq); +} + +void +ExtiHard::disable () +{ + if (exti_hardware[n_].enabled) + { + if (!--*exti_hardware[n_].enabled) + nvic_disable_irq (exti_hardware[n_].irq); + } + else + nvic_disable_irq (exti_hardware[n_].irq); + EXTI_IMR &= ~(1u << n_); + EXTI_PR = 1u << n_; +} + +bool +ExtiHard::mask () +{ + bool irq_enabled = nvic_get_irq_enabled (exti_hardware[n_].irq); + if (irq_enabled) + nvic_disable_irq (exti_hardware[n_].irq); + return irq_enabled; +} + +void +ExtiHard::unmask (bool saved_state) +{ + if (saved_state) + nvic_enable_irq (exti_hardware[n_].irq); +} + +void +ExtiHard::set_trigger (Edge edge) +{ + switch (edge) + { + case Edge::RISING: + EXTI_RTSR |= 1u << n_; + EXTI_FTSR &= ~(1u << n_); + break; + case Edge::FALLING: + EXTI_RTSR &= ~(1u << n_); + EXTI_FTSR |= 1u << n_; + break; + case Edge::BOTH: + EXTI_RTSR |= (1u << n_); + EXTI_FTSR |= (1u << n_); + break; + } +} + +void +ExtiHard::set_source (uint32_t gpio_port) +{ + int port; + switch (gpio_port) + { + case GPIOA: + port = 0; + break; + case GPIOB: + port = 1; + break; + case GPIOC: + port = 2; + break; + case GPIOD: + port = 3; + break; +#if defined GPIOE + case GPIOE: + port = 4; + break; +#endif +#if defined GPIOF + case GPIOF: + port = 5; + break; +#endif +#if defined GPIOG + case GPIOG: + port = 6; + break; +#endif +#if defined GPIOH + case GPIOH: + port = 7; + break; +#endif +#if defined GPIOI + case GPIOI: + port = 8; + break; +#endif + default: + assert_unreachable (); + } + int shift = (n_ % 4) * 4; + int reg = n_ / 4; + uint32_t mask = 0xf << shift; + uint32_t bits = port << shift; +#if defined AFIO_BASE + AFIO_EXTICR (reg) = (AFIO_EXTICR (reg) & ~mask) | bits; +#else + SYSCFG_EXTICR (reg) = (SYSCFG_EXTICR (reg) & ~mask) | bits; +#endif +} + +void +ExtiHard::isr () +{ + handler_ (); +} + +} // namespace ucoo diff --git a/ucoo/hal/exti/exti.stm32.hh b/ucoo/hal/exti/exti.stm32.hh new file mode 100644 index 0000000..90a8098 --- /dev/null +++ b/ucoo/hal/exti/exti.stm32.hh @@ -0,0 +1,86 @@ +#ifndef ucoo_hal_exti_exti_stm32_hh +#define ucoo_hal_exti_exti_stm32_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2015 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/intf/exti.hh" + +#include + +namespace ucoo { + +/// External interrupt on STM32. +class ExtiHard : public Exti +{ + public: + enum class Edge + { + RISING = 1, + FALLING = 2, + BOTH = 3 + }; + public: + /// Constructor, take the EXTI number. + ExtiHard (int n); + /// Constructor, shortcut to set source. + ExtiHard (uint32_t gpio_port, int n); + /// Constructor, shortcut to set source and trigger. + ExtiHard (uint32_t gpio_port, int n, Edge edge); + /// Destructor. + ~ExtiHard (); + /// See Exti::enable. + void enable (); + /// See Exti::disable. + void disable (); + /// See Exti::mask. + bool mask (); + /// See Exti::unmask. + void unmask (bool saved_state); + /// Set trigger edge. + void set_trigger (Edge edge); + /// Select source, take GPIO port address. + void set_source (uint32_t gpio_port); + /// Handle interrupts. + void isr (); + private: + /// EXTI line number. + int n_; +}; + +inline +ExtiHard::ExtiHard (uint32_t gpio_port, int n) + : ExtiHard (n) +{ + set_source (gpio_port); +} + +inline +ExtiHard::ExtiHard (uint32_t gpio_port, int n, Edge edge) + : ExtiHard (gpio_port, n) +{ + set_trigger (edge); +} + +} // namespace ucoo + +#endif // ucoo_hal_exti_exti_stm32_hh diff --git a/ucoo/hal/exti/test/Makefile b/ucoo/hal/exti/test/Makefile new file mode 100644 index 0000000..c2a7418 --- /dev/null +++ b/ucoo/hal/exti/test/Makefile @@ -0,0 +1,9 @@ +BASE = ../../../.. + +TARGETS = stm32f4 stm32f1 +PROGS = test_exti +test_exti_SOURCES = test_exti.stm32.cc + +MODULES = ucoo/hal/gpio ucoo/hal/exti ucoo/utils + +include $(BASE)/build/top.mk diff --git a/ucoo/hal/exti/test/test_exti.stm32.cc b/ucoo/hal/exti/test/test_exti.stm32.cc new file mode 100644 index 0000000..57b80a5 --- /dev/null +++ b/ucoo/hal/exti/test/test_exti.stm32.cc @@ -0,0 +1,66 @@ +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2015 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/arch/arch.hh" +#include "ucoo/hal/gpio/gpio.hh" +#include "ucoo/hal/exti/exti.hh" +#include "ucoo/utils/delay.hh" + +#include + +ucoo::Gpio *led4p; + +void +led4_handler () +{ + led4p->toggle (); +} + +int +main (int argc, const char **argv) +{ + ucoo::arch_init (argc, argv); + rcc_periph_clock_enable (RCC_GPIOB); + rcc_periph_clock_enable (RCC_GPIOD); + // For this test, shorten B6 & B7 to have loopback. + ucoo::Gpio loop_out (GPIOB, 6); + ucoo::Gpio loop_in (GPIOB, 7); + ucoo::Gpio led3 (GPIOD, 13); + ucoo::Gpio led4 (GPIOD, 12); + led4p = &led4; + ucoo::ExtiHard exti (7); + exti.set_source (GPIOB); + exti.set_trigger (ucoo::ExtiHard::Edge::RISING); + exti.register_event (led4_handler); + exti.enable (); + loop_out.output (); + led3.output (); + led4.output (); + while (1) + { + loop_out.toggle (); + led3.set (loop_in.get ()); + ucoo::delay (1); + } + return 0; +} diff --git a/ucoo/intf/exti.hh b/ucoo/intf/exti.hh new file mode 100644 index 0000000..a943a80 --- /dev/null +++ b/ucoo/intf/exti.hh @@ -0,0 +1,56 @@ +#ifndef ucoo_intf_exti_hh +#define ucoo_intf_exti_hh +// ucoolib - Microcontroller object oriented library. {{{ +// +// Copyright (C) 2015 Nicolas Schodet +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// }}} +#include "ucoo/utils/function.hh" + +namespace ucoo { + +/// External interrupt interface. +class Exti +{ + public: + /// Enable. + virtual void enable () = 0; + /// Disable. + virtual void disable () = 0; + /// Temporary mask interrupt, return previous state. + virtual bool mask () = 0; + /// Unmask interrupt. + virtual void unmask (bool saved_state) = 0; + /// Register a handler called on event. + template + void register_event (F handler) + { handler_ = handler; } + protected: + /// Default constructor. + Exti () { } + protected: + /// Handler called on event. + Function handler_; +}; + +} // namespace ucoo + +#endif // ucoo_intf_exti_hh -- cgit v1.2.3