µOS++ IIIe / CMSIS++ / POSIX++ Reference  v6.3.11
“Perfekt ist nicht gut genug”
The third edition of µOS++ and CMSIS++, a proposal for the next generation CMSIS, written in C++.
os-main.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the µOS++ distribution.
3  * (https://github.com/micro-os-plus)
4  * Copyright (c) 2016 Liviu Ionescu.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #include <cmsis-plus/rtos/os.h>
30 
31 // ----------------------------------------------------------------------------
32 
33 using namespace os;
34 
35 // ----------------------------------------------------------------------------
36 
41 extern "C" void
42 os_goodbye (void);
43 
44 namespace
45 {
46  // --------------------------------------------------------------------------
47 
48  // Since the native threads have a single argument, and it is better to
49  // avoid C++11 tuples and function objects, there is no other simple
50  // way than to pack the args in a structure and use it by the
51  // trampoline to invoke the os_main().
52 
53 #pragma GCC diagnostic push
54 #pragma GCC diagnostic ignored "-Wpadded"
55 
56  using main_args_t = struct
57  {
58  int argc;
59  char** argv;
60  };
61 
62 #pragma GCC diagnostic pop
63 
64  static main_args_t main_args;
65 
66  // --------------------------------------------------------------------------
67 
68  [[noreturn]] static void
69  _main_trampoline (void)
70  {
71  trace::puts ("");
72  trace::dump_args (main_args.argc, main_args.argv);
73 
74  int code = os_main (main_args.argc, main_args.argv);
75  trace::printf ("%s() exit = %d\n", __func__, code);
76 
77  // Exit will run the atexit() and destructors, then
78  // terminate gracefully.
79  std::exit (code);
80  }
81 
82 // --------------------------------------------------------------------------
83 
84 } /* namespace */
85 
90 // ----------------------------------------------------------------------------
92 
93 // Intentionally a raw pointer, to prevent destruction.
95 
96 #if defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
97 
98 // Necessarily static, on Cortex-M the reset stack will be used
99 // as MSP for the interrupts, so the current stack must be freed
100 // and os_main() shall run on its own stack.
102 static std::aligned_storage<sizeof(main_thread), alignof(main_thread)>::type os_main_thread_;
103 
104 #endif /* defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
105 
109 int
110 #if !defined(__APPLE__)
111 __attribute__((weak))
112 #endif
113 main (int argc, char* argv[])
114 {
115  using namespace os::rtos;
116 
117  trace::printf ("\nµOS++ IIIe version " OS_STRING_RTOS_IMPL_VERSION ".\n");
118  trace::printf ("Copyright (c) 2016 Liviu Ionescu.\n");
119 
121 
122  trace::printf ("Scheduler frequency: %u ticks/sec.\n",
124  trace::printf ("Default stack size: %u bytes.\n",
126 #if defined(OS_HAS_INTERRUPTS_STACK)
127  trace::printf ("Interrupts stack size: %u bytes.\n",
128  interrupts::stack ()->size ());
129 #endif /* defined(OS_HAS_INTERRUPTS_STACK) */
130 
131 #if defined(__clang__)
132  trace::printf ("Built with clang " __VERSION__);
133 #else
134  trace::printf ("Built with GCC " __VERSION__);
135 #endif
136 
137 #if defined(__EXCEPTIONS)
138  trace::printf (", with exceptions");
139 #else
140  trace::printf (", no exceptions");
141 #endif
142  trace::puts (".\n");
143 
145 
146  // Store the parameters in the static structure, to be used by os_main().
147  main_args.argc = argc;
148  main_args.argv = argv;
149 
150 #if defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
151 
152  // Running the constructor manually has the additional advantage of
153  // not registering any destructor, and for main this is important,
154  // since the destructors are executed on its context, and it cannot
155  // destruct itself.
156  new (&os_main_thread_) main_thread
157  { "main", reinterpret_cast<thread::func_t> (_main_trampoline), nullptr};
158 
159  os_main_thread = &os_main_thread_;
160 
161 #else
162 
165  os_main_thread = new thread (
166  "main", reinterpret_cast<thread::func_t> (_main_trampoline), nullptr,
167  attr);
168 
169 #endif /* defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
170 
171 #if !defined(OS_USE_RTOS_PORT_SCHEDULER)
173 #endif /* !defined(OS_USE_RTOS_PORT_SCHEDULER) */
174 
175  // Execution will proceed to first registered thread, possibly
176  // "idle", which will immediately lower its priority,
177  // and at a certain moment will reach os_main().
178  scheduler::start ();
179 
180  /* NOTREACHED */
181 }
182 
183 void
184 #if !defined(__APPLE__)
185 __attribute__((weak))
186 #endif
188 {
189 #if defined(TRACE)
190 
191  trace::printf ("\n");
192 
193 #if !defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
194 
195  // Application memory.
197 
198 #if defined(OS_INTEGER_RTOS_DYNAMIC_MEMORY_SIZE_BYTES)
200 #endif /* defined(OS_INTEGER_RTOS_DYNAMIC_MEMORY_SIZE_BYTES) */
201 
202 #endif /* !defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
203 
204  class rtos::thread::stack& st = os_main_thread->stack ();
205 
206  trace::printf ("Main thread stack: %u/%u bytes used\n",
207  st.size () - st.available (), st.size ());
208 
209 #if defined(OS_HAS_INTERRUPTS_STACK)
210  trace::printf (
211  "Interrupts stack: %u/%u bytes used\n",
212  rtos::interrupts::stack ()->size ()
213  - rtos::interrupts::stack ()->available (),
214  rtos::interrupts::stack ()->size ());
215 #endif /* defined(OS_HAS_INTERRUPTS_STACK) */
216 
217  trace::printf ("\nHasta la Vista!\n");
218 
219 #endif /* defined(TRACE) */
220 }
221 // ----------------------------------------------------------------------------
Thread attributes.
Definition: os-thread.h:769
Thread stack.
Definition: os-thread.h:405
static std::size_t default_size(void)
Get the default stack size.
Definition: os-thread.h:2191
void exit(int code)
Definition: exit.c:78
int puts(const char *s)
Write the string and a line terminator to the trace device.
Definition: trace.cpp:108
class thread::stack * stack(void)
Get the interrupts stack.
Definition: os-core.cpp:528
memory_resource * get_default_resource(void) noexcept
Get the default application memory manager.
int main(int argc, char *argv[])
Default implementation of main().
Definition: os-main.cpp:113
class thread::stack & stack(void)
Get the thread context stack.
Definition: os-thread.h:2397
#define OS_INTEGER_RTOS_MAIN_STACK_SIZE_BYTES
Define the main thread stack size, in bytes.
void os_startup_create_thread_idle(void)
Create the idle thread.
void os_goodbye(void)
std::size_t size(void)
Get the stack size.
Definition: os-thread.h:2134
System namespace.
Template of a POSIX compliant thread with local stack.
Definition: os-thread.h:1773
void trace_print_statistics(void)
Print a long message with usage statistics.
Definition: os-memory.h:1419
memory_resource * get_default_resource(void) noexcept
Get the default RTOS system memory manager.
Definition: os-memory.h:1106
void start(void)
Start the RTOS scheduler.
Definition: os-core.cpp:159
void os_terminate_goodbye(void)
Display statistics and say goodbye before terminating.
Definition: os-main.cpp:187
POSIX compliant thread, using the default RTOS allocator.
Definition: os-thread.h:235
std::size_t th_stack_size_bytes
Size of the user defined storage for the thread stack, in bytes.
Definition: os-thread.h:830
Single file CMSIS++ RTOS definitions.
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
static const attributes initializer
Default thread initialiser.
Definition: os-thread.h:967
static constexpr uint32_t frequency_hz
SysTick frequency in Hz.
Definition: os-clocks.h:474
void *(*)(func_args_t args) func_t
Type of thread function.
Definition: os-thread.h:396
RTOS namespace.
Definition: os-flags.h:46
thread & thread(void)
Get the current running thread.
Definition: os-thread.cpp:1481
void dump_args(int argc, char *argv[])
Write the argv[] array to the trace device.
Definition: trace.cpp:140
result_t initialize(void)
Initialise the RTOS scheduler.
Definition: os-core.cpp:131
#define OS_STRING_RTOS_IMPL_VERSION
Definition: os-versions.h:57
rtos::thread * os_main_thread
Definition: os-main.cpp:94
std::size_t available(void)
Compute how much available stack remains.
Definition: os-thread.cpp:191
int os_main(int argc, char *argv[])
Application entry point, running on the main thread context.