summaryrefslogtreecommitdiff
path: root/ucoo/utils
diff options
context:
space:
mode:
authorNicolas Schodet2016-07-25 15:18:40 +0200
committerNicolas Schodet2019-10-09 23:05:44 +0200
commit4695b47da68a5b2f75270bea21e15b8f1b9fd6ff (patch)
tree6e5ef4d34ee69bcd6c6627f25a0ca3aa902d47e3 /ucoo/utils
parentd7df91926bdb529e68eff9a215aef72072803b6e (diff)
Switch to CMSIS
Diffstat (limited to 'ucoo/utils')
-rw-r--r--ucoo/utils/bits.hh45
-rw-r--r--ucoo/utils/buffer.hh74
-rw-r--r--ucoo/utils/buffer.tcc125
-rw-r--r--ucoo/utils/delay.arm.cc33
-rw-r--r--ucoo/utils/irq_locked.hh45
-rw-r--r--ucoo/utils/rate_limit.tcc2
-rw-r--r--ucoo/utils/table_lookup.hh51
-rw-r--r--ucoo/utils/test/Makefile2
-rw-r--r--ucoo/utils/test/test_delay.cc30
-rw-r--r--ucoo/utils/trace.hh2
-rw-r--r--ucoo/utils/trace.tcc4
11 files changed, 381 insertions, 32 deletions
diff --git a/ucoo/utils/bits.hh b/ucoo/utils/bits.hh
new file mode 100644
index 0000000..3c1916b
--- /dev/null
+++ b/ucoo/utils/bits.hh
@@ -0,0 +1,45 @@
+#ifndef ucoo_utils_bits_hh
+#define ucoo_utils_bits_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2016 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.
+//
+// }}}
+
+namespace ucoo {
+
+template<typename T>
+T
+bits (int index)
+{
+ return 1 << index;
+}
+
+template<typename T, typename... Indices>
+T
+bits (int index, Indices... indices)
+{
+ return bits<T> (index) | bits<T> (indices...);
+}
+
+} // namespace ucoo
+
+#endif // ucoo_utils_bits_hh
diff --git a/ucoo/utils/buffer.hh b/ucoo/utils/buffer.hh
new file mode 100644
index 0000000..b665d25
--- /dev/null
+++ b/ucoo/utils/buffer.hh
@@ -0,0 +1,74 @@
+#ifndef ucoo_utils_buffer_hh
+#define ucoo_utils_buffer_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2016 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.
+//
+// }}}
+
+namespace ucoo {
+
+/// Buffer with linear reads and writes. Looks like a fifo but without thread
+/// safety and with poorer performance, but access is linear.
+///
+/// Warning: no safety net, make sure not to read non present elements or to
+/// write more elements than available space.
+template<typename T, int max_size>
+class Buffer
+{
+ public:
+ /// Constructor, empty buffer.
+ Buffer ();
+ /// Test whether the buffer is empty.
+ bool empty () const;
+ /// Test whether the buffer is full (no element can be written, but see
+ /// rewind()).
+ bool full () const;
+ /// Return the number of available elements.
+ int size () const;
+ /// Return the available space for elements.
+ int room () const;
+ /// Return pointer to readable elements.
+ const T *read () const;
+ /// Drop a number of elements after they have been read (or not).
+ void drop (int n);
+ /// Return pointer to readable elements and drop them (remember: not
+ /// thread safe).
+ const T *read (int n);
+ /// Return pointer to writable space.
+ T *write ();
+ /// Increase the number of available elements (just written).
+ void written (int n);
+ /// Return pointer to writable space and increase the number of available
+ /// elements (remember: not thread safe).
+ T *write (int n);
+ /// Move data to begin of buffer to make room after it.
+ void rewind ();
+ private:
+ T data_[max_size];
+ T *begin_, *end_;
+};
+
+} // namespace ucoo
+
+#include "buffer.tcc"
+
+#endif // ucoo_utils_buffer_hh
diff --git a/ucoo/utils/buffer.tcc b/ucoo/utils/buffer.tcc
new file mode 100644
index 0000000..bc25bb7
--- /dev/null
+++ b/ucoo/utils/buffer.tcc
@@ -0,0 +1,125 @@
+#ifndef ucoo_utils_buffer_tcc
+#define ucoo_utils_buffer_tcc
+// buffer.tcc
+// {{{
+//
+// Copyright (C) 2016 Nicolas Schodet
+//
+// 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 2 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, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// Contact :
+// Web: http://ni.fr.eu.org/
+// Email: <nico at ni.fr.eu.org>
+// }}}
+#include <algorithm>
+
+namespace ucoo {
+
+template<typename T, int max_size>
+Buffer<T, max_size>::Buffer ()
+ : begin_ (data_), end_ (data_)
+{
+}
+
+template<typename T, int max_size>
+bool
+Buffer<T, max_size>::empty () const
+{
+ return begin_ == end_;
+}
+
+template<typename T, int max_size>
+bool
+Buffer<T, max_size>::full () const
+{
+ return end_ == &data_[max_size];
+}
+
+template<typename T, int max_size>
+int
+Buffer<T, max_size>::size () const
+{
+ return end_ - begin_;
+}
+
+template<typename T, int max_size>
+int
+Buffer<T, max_size>::room () const
+{
+ return &data_[max_size] - end_;
+}
+
+template<typename T, int max_size>
+const T *
+Buffer<T, max_size>::read () const
+{
+ return begin_;
+}
+
+template<typename T, int max_size>
+void
+Buffer<T, max_size>::drop (int n)
+{
+ begin_ += n;
+ if (empty ())
+ begin_ = end_ = &data_[0];
+}
+
+template<typename T, int max_size>
+const T *
+Buffer<T, max_size>::read (int n)
+{
+ drop (n);
+ return read ();
+}
+
+template<typename T, int max_size>
+T *
+Buffer<T, max_size>::write ()
+{
+ return end_;
+}
+
+template<typename T, int max_size>
+void
+Buffer<T, max_size>::written (int n)
+{
+ end_ += n;
+}
+
+template<typename T, int max_size>
+T *
+Buffer<T, max_size>::write (int n)
+{
+ T *r = write ();
+ written (n);
+ return r;
+}
+
+template<typename T, int max_size>
+void
+Buffer<T, max_size>::rewind ()
+{
+ if (begin_ != &data_[0])
+ {
+ std::copy (begin_, end_, &data_[0]);
+ end_ -= begin_ - &data_[0];
+ begin_ = &data_[0];
+ }
+}
+
+} // namespace ucoo
+
+#endif // ucoo_utils_buffer_tcc
diff --git a/ucoo/utils/delay.arm.cc b/ucoo/utils/delay.arm.cc
index 244d521..086ca4c 100644
--- a/ucoo/utils/delay.arm.cc
+++ b/ucoo/utils/delay.arm.cc
@@ -22,12 +22,11 @@
//
// }}}
#include "delay.arm.hh"
+#include "ucoo/arch/reg.hh"
+#include "ucoo/arch/rcc.stm32.hh"
#include <algorithm>
-#include <libopencm3/cm3/systick.h>
-#include <libopencm3/stm32/rcc.h>
-
namespace ucoo {
void
@@ -35,21 +34,21 @@ delay_us (int us)
{
// Suppose that frequency is a multiple of 8 MHz (to avoid 64 bit
// division).
- int systick_mhz = rcc_ahb_frequency / (8 * 1000000);
+ int systick_mhz = rcc_ahb_freq_hz / (8 * 1000000);
int cycles = systick_mhz * us;
- STK_CSR = 0;
+ reg::SysTick->CTRL = 0;
// Loop several times if cycles is too big for the systick timer. Some
// nanoseconds are lost every second, I can live with that, it simplifies
// code.
while (cycles)
{
int loop_cycles = std::min (1 << 24, cycles);
- STK_RVR = loop_cycles - 1;
- STK_CVR = 0;
- STK_CSR = STK_CSR_ENABLE;
- while (!(STK_CSR & STK_CSR_COUNTFLAG))
+ reg::SysTick->LOAD = loop_cycles - 1;
+ reg::SysTick->VAL = 0;
+ reg::SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
+ while (!(reg::SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
;
- STK_CSR = 0;
+ reg::SysTick->CTRL = 0;
cycles -= loop_cycles;
}
}
@@ -59,16 +58,16 @@ delay_ns (int ns)
{
// Suppose that frequency is a multiple of 1 MHz (to avoid 64 bit
// division).
- int hclock_mhz = rcc_ahb_frequency / 1000000;
+ int hclock_mhz = rcc_ahb_freq_hz / 1000000;
int cycles = (hclock_mhz * ns + 999) / 1000;
- STK_CSR = 0;
+ reg::SysTick->CTRL = 0;
// Loop once, ns is supposed to be small.
- STK_RVR = cycles - 1;
- STK_CVR = 0;
- STK_CSR = STK_CSR_CLKSOURCE_AHB | STK_CSR_ENABLE;
- while (!(STK_CSR & STK_CSR_COUNTFLAG))
+ reg::SysTick->LOAD = cycles - 1;
+ reg::SysTick->VAL = 0;
+ reg::SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk;
+ while (!(reg::SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
;
- STK_CSR = 0;
+ reg::SysTick->CTRL = 0;
}
} // namespace ucoo
diff --git a/ucoo/utils/irq_locked.hh b/ucoo/utils/irq_locked.hh
new file mode 100644
index 0000000..5f4a1a0
--- /dev/null
+++ b/ucoo/utils/irq_locked.hh
@@ -0,0 +1,45 @@
+#ifndef ucoo_utils_irq_locked_hh
+#define ucoo_utils_irq_locked_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2016 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/common.hh"
+
+namespace ucoo {
+
+/// Make sure interrupts are unlocked when scope is exited.
+class IrqLocked
+{
+ irq_flags_t flags_;
+ public:
+ /// Constructor, lock interrupts.
+ IrqLocked () { flags_ = irq_lock (); }
+ /// Destructor, unlock.
+ ~IrqLocked () { irq_restore (flags_); }
+ /// No copy constructor.
+ IrqLocked (const IrqLocked &) = delete;
+};
+
+} // namespace ucoo
+
+#endif // ucoo_utils_irq_locked_hh
diff --git a/ucoo/utils/rate_limit.tcc b/ucoo/utils/rate_limit.tcc
index 0d034e3..938c20f 100644
--- a/ucoo/utils/rate_limit.tcc
+++ b/ucoo/utils/rate_limit.tcc
@@ -46,7 +46,7 @@ template<typename Timer>
void
RateLimit<Timer>::set_limit (int rate_num, int rate_denum)
{
- int freq = timer_.get_freq ();
+ int freq = timer_.get_freq_hz ();
interval_ = freq * rate_denum / rate_num;
ucoo::assert (interval_ <= Timer::max / 2 + 1);
next_ = timer_.get_value ();
diff --git a/ucoo/utils/table_lookup.hh b/ucoo/utils/table_lookup.hh
new file mode 100644
index 0000000..ffd8e3d
--- /dev/null
+++ b/ucoo/utils/table_lookup.hh
@@ -0,0 +1,51 @@
+#ifndef ucoo_utils_table_lookup_hh
+#define ucoo_utils_table_lookup_hh
+// ucoolib - Microcontroller object oriented library. {{{
+//
+// Copyright (C) 2016 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/common.hh"
+
+namespace ucoo {
+
+template<typename K, typename V>
+struct LookupTable
+{
+ K key;
+ V val;
+};
+
+template<typename K, typename V, int N>
+V
+simple_table_lookup (const LookupTable<K, V> (&t)[N], K key)
+{
+ for (int i = 0; i < N; i++)
+ {
+ if (t[i].key == key)
+ return t[i].val;
+ }
+ assert_unreachable ();
+}
+
+} // namespace ucoo
+
+#endif // ucoo_utils_table_lookup_hh
diff --git a/ucoo/utils/test/Makefile b/ucoo/utils/test/Makefile
index 6f2094e..1255cae 100644
--- a/ucoo/utils/test/Makefile
+++ b/ucoo/utils/test/Makefile
@@ -9,6 +9,6 @@ test_crc_SOURCES = test_crc.cc
test_function_SOURCES = test_function.cc
test_pool_SOURCES = test_pool.cc
-MODULES = ucoo/utils ucoo/base/test ucoo/hal/usb
+MODULES = ucoo/utils ucoo/base/test ucoo/hal/usb ucoo/hal/gpio
include $(BASE)/build/top.mk
diff --git a/ucoo/utils/test/test_delay.cc b/ucoo/utils/test/test_delay.cc
index b56c7c1..87945d3 100644
--- a/ucoo/utils/test/test_delay.cc
+++ b/ucoo/utils/test/test_delay.cc
@@ -23,39 +23,47 @@
// }}}
#include "ucoo/utils/delay.hh"
#include "ucoo/arch/arch.hh"
-
-#include <libopencm3/stm32/rcc.h>
-#include <libopencm3/stm32/gpio.h>
+#include "ucoo/hal/gpio/gpio.hh"
+#include "ucoo/common.hh"
int
main (int argc, const char **argv)
{
ucoo::arch_init (argc, argv);
- rcc_periph_clock_enable (RCC_GPIOD);
- gpio_mode_setup (GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
- GPIO12 | GPIO13 | GPIO14 | GPIO15);
- gpio_clear (GPIOD, GPIO12 | GPIO13 | GPIO14 | GPIO15);
+ ucoo::GPIOD.enable ();
+ ucoo::Gpio leds[] =
+ {
+ ucoo::GPIOD[12],
+ ucoo::GPIOD[13],
+ ucoo::GPIOD[14],
+ ucoo::GPIOD[15],
+ };
+ for (int i = 0; i < ucoo::lengthof (leds); i++)
+ {
+ leds[i].output ();
+ leds[i].reset ();
+ }
int i, j;
while (1)
{
for (i = 0; i < 4; i++)
{
- gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ leds[i % 4].toggle ();
ucoo::delay (1);
}
for (i = 0; i < 16; i++)
{
- gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ leds[i % 4].toggle ();
ucoo::delay_ms (250);
}
for (i = 0; i < 16000; i++)
{
- gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ leds[i % 4].toggle ();
ucoo::delay_us (250);
}
for (i = 0; i < 16; i++)
{
- gpio_toggle (GPIOD, GPIO12 << (i % 4));
+ leds[i % 4].toggle ();
for (j = 0; j < 1000; j++)
ucoo::delay_us (250);
}
diff --git a/ucoo/utils/trace.hh b/ucoo/utils/trace.hh
index dbbf442..7cae33d 100644
--- a/ucoo/utils/trace.hh
+++ b/ucoo/utils/trace.hh
@@ -42,7 +42,7 @@ class TraceBuffer
/// Maximum number of arguments.
static const int args_nb = 4;
/// Maximum number of trace entries.
- static const int entries_nb = 32;
+ static const int entries_nb = 512;
public:
/// Constructor.
TraceBuffer (const Timestamp &timestamp = Timestamp ());
diff --git a/ucoo/utils/trace.tcc b/ucoo/utils/trace.tcc
index e48c5d8..8d1fc29 100644
--- a/ucoo/utils/trace.tcc
+++ b/ucoo/utils/trace.tcc
@@ -68,7 +68,9 @@ TraceBuffer<Timestamp>::operator() (const char *str, int a0, int a1, int a2)
{
timestamp_ (entries[index]);
entries[index].str = str;
- entries[index].args = { a0, a1, a2 };
+ entries[index].args[0] = a0;
+ entries[index].args[1] = a1;
+ entries[index].args[2] = a2;
index = (index + 1) % entries_nb;
}