OpenMPTL - ARM Cortex (common)
C++ Microprocessor Template Library
vector_table.hpp
Go to the documentation of this file.
1 /*
2  * OpenMPTL - C++ Microprocessor Template Library
3  *
4  * Copyright (C) 2012-2017 Axel Burri <axel@tty0.ch>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #ifndef ARM_CORTEX_COMMON_VECTOR_TABLE_HPP_INCLUDED
22 #define ARM_CORTEX_COMMON_VECTOR_TABLE_HPP_INCLUDED
23 
24 #include <arch/nvic.hpp>
25 #include <typelist.hpp>
26 #include <simulation.hpp>
27 #include <type_traits>
28 #include <compiler.h>
29 
30 namespace mptl {
31 
32 #ifndef OPENMPTL_SIMULATION
33 static_assert(sizeof(isr_t) == 4, "wrong size for isr function pointer");
34 static_assert(alignof(isr_t) == 4, "wrong alignment for isr function pointer table");
35 static_assert(sizeof(uint32_t *) == 4, "wrong size for top-of-stack pointer");
36 static_assert(alignof(uint32_t *) == 4, "wrong alignment for top-of-stack pointer");
37 #endif
38 
39 template<std::size_t vt_size>
41  const uint32_t * stack_top;
42  isr_t isr_vector[vt_size];
43 };
44 
45 
46 namespace mpl
47 {
48  /**
49  * Provides a arm_cortex_vector_table in static member "value" which
50  * can be used to fill linker section ".isr_vector", containing
51  * stack_top and all values of the mptl::irq_handler<> traits.
52  *
53  * Template arguments:
54  *
55  * - stack_top: pointer to reset value of stack pointer
56  * - Tp: mptl::irq_handler<> traits
57  */
58  template<const uint32_t *stack_top, typename... Tp>
59  struct vector_table_impl {
60  static constexpr std::size_t vt_size = sizeof...(Tp);
61  static constexpr std::size_t size = vt_size + 1;
62  static constexpr arm_cortex_vector_table<vt_size> value = { stack_top, { Tp::value... } };
63 
64 #ifdef OPENMPTL_SIMULATION
65  /** Dump demangled irq_handler types to std::cout */
66  static void dump_types(void) {
67  std::cout << "*** irq handler types:" << std::endl;
68  dump_irq_types<Tp...>()();
69  }
70 #endif
71 
72 #if 0
73  /* With gcc 4.x, the section attribute was honored within static
74  * template member variables. To create the vector table, the
75  * following statement was used:
76  *
77  * mptl::vector_table< &_stack_top, resources > vector_table;
78  *
79  * As of gcc 5.x (as well as clang), this does not work any more,
80  * section attributes are not honored for static template
81  * variables. Maybe related to:
82  * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70435
83  */
84  static isr_t isr_vector[size] __used __attribute__ ((section(".isr_vector")));
85 #endif
86  };
87 
88 #if 0
89  /* see comment above */
90  template<const uint32_t *stack_top, typename... Tp>
91  isr_t vector_table_impl<stack_top, Tp...>::isr_vector[size] = {
92  (isr_t)stack_top,
93  Tp::value...
94  };
95 #endif
96 
97  /** recursively build the vector table */
98  template< unsigned int N,
99  int irqn_offset,
100  typename irq_handler_list,
101  isr_t default_isr,
102  const uint32_t *stack_top,
103  typename... Tp >
104  struct make_vector_table
105  {
106  static constexpr int irqn = (N - 1) + irqn_offset;
107  using irq_handler_resource = mpl::unique_irq_handler<irq_handler_list, irqn>;
108  using irq_handler_default = irq_handler< irq_base< irqn >, default_isr >;
109 
110  /** irq_handler<> from irq_handler<irqn> in irq_handler_list if
111  * present, default_isr if not. default_isr if irqn is a
112  * reserved_irqn() */
113  using irq_handler_type = typename std::conditional<
114  ( irq::reserved_irqn(irqn) ||
115  std::is_void< irq_handler_resource >::value ),
116  irq_handler_default,
117  irq_handler_resource >::type;
118 
119  /** recursion */
120  using type = typename make_vector_table<
121  N - 1,
122  irqn_offset,
123  irq_handler_list,
124  default_isr,
125  stack_top,
126  irq_handler_type,
127  Tp...
128  >::type;
129  };
130 
131  /* last irq number (N) is irq::reset::irqn */
132  template< int irqn_offset,
133  typename irq_handler_list,
134  isr_t default_isr,
135  const uint32_t * stack_top,
136  typename... Tp >
137  struct make_vector_table< 0, irqn_offset, irq_handler_list, default_isr, stack_top, Tp... > {
138  using type = vector_table_impl<stack_top, Tp...>;
139  };
140 } // namespace mpl
141 
142 
143 /**
144  * Provides a static vector table (value[], see vector_table_impl
145  * above), to be initialized in section ".isr_vector".
146  *
147  * Example:
148  *
149  * extern const uint32_t _stack_top; // provided by linker script
150  * using resources = mptl::typelist<
151  * mptl::irq_handler< typename mptl::irq::reset, my_reset_isr >,
152  * ...
153  * >;
154  * using vector_table = mptl::vector_table<&_stack_top, resources>;
155  * const auto isr_vector __attribute__((used, section(".isr_vector"))) = vector_table::value;
156  *
157  * Template arguments:
158  *
159  * - stack_top: pointer to reset value of stack pointer
160  *
161  * - irq_handler_list: typelist<>, containing mptl::irq_handler<>
162  * traits (other traits are ignored)
163  *
164  * - default_isr: isr_t function pointer, used for all irq's which
165  * are not listed in irq_handler_list. Defaults to "nullptr".
166  *
167  */
168 template<const uint32_t *stack_top, typename irq_handler_list, isr_t default_isr = nullptr >
170 : mpl::make_vector_table<
171  irq::numof_interrupt_channels - irq::reset::irqn, /* start index */
172  irq::reset::irqn, /* irqn_offset (negative) */
173  irq_handler_list,
174  default_isr,
175  stack_top
176  >::type
177 {
179 
180  /** offset of irq_channel<0> in arm_cortex_vector_table::isr_vector[] */
181  static constexpr int irq_channel_offset = -irq::reset::irqn;
182  static constexpr int numof_core_exceptions = -irq::reset::irqn;
183 
184  static_assert(irq::reset::irqn < 0, "irq::reset::irqn must be a negative value");
185  static_assert(irq::numof_interrupt_channels >= 0, "invalid irq::numof_interrupt_channels");
186  static_assert(sizeof(type::value) == sizeof(isr_t) * (1 + irq::numof_interrupt_channels + numof_core_exceptions),
187  "IRQ vector table size error");
188 
189 #ifdef OPENMPTL_SIMULATION
190  static void dump_size(void) {
191  int w = 3;
192  std::cout << "*** vector table size:" << std::endl;
193  std::cout << "stack_top pointer: " << std::setw(w) << 1 << std::endl;
194  std::cout << "cortex core exceptions: " << std::setw(w) << numof_core_exceptions << std::endl;
195  std::cout << "irq channels: " << std::setw(w) << irq::numof_interrupt_channels << std::endl;
196  std::cout << "total size: " << std::setw(w) << type::size << std::endl;
197  }
198 
199  /**
200  * Dump the isr_vector table.
201  *
202  * Not very useful, as it prints the pointers to irq_handler from
203  * simulation functions.
204  */
205  static void dump_vector(void) {
206  int vt_size = type::vt_size;
207  auto vt = type::value;
208 
209  std::cout << "*** vector table dump:" << std::endl;
210  std::cout << std::dec << " 0 (TOS) : 0x" << std::hex << (unsigned long)vt.stack_top << std::endl;
211  for(int i = 0; i < vt_size; i++) {
212  std::cout << std::dec << std::setw(3) << (1 + i) << " " <<
213  "(" << std::setw(3) << (i - irq_channel_offset) << ")" <<
214  " : 0x" << std::hex << (unsigned long)vt.isr_vector[i] << std::endl;
215  }
216  }
217 #endif // OPENMPTL_SIMULATION
218 };
219 
220 } // namespace mptl
221 
222 #endif // ARM_CORTEX_COMMON_VECTOR_TABLE_HPP_INCLUDED
Definition: vector_table.hpp:40
static constexpr bool reserved_irqn(int irqn)
Definition: nvic.hpp:134
#define __used
Provides a static vector table (value[], see vector_table_impl above), to be initialized in section "...
Definition: vector_table.hpp:169
const uint32_t * stack_top
Definition: vector_table.hpp:41
static constexpr int irqn
Definition: nvic.hpp:36
void(*const isr_t)(void)
isr_t isr_vector[vt_size]
Definition: vector_table.hpp:42