µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
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#if defined(__clang__)
34#pragma clang diagnostic ignored "-Wc++98-compat"
35#endif
36
37// ----------------------------------------------------------------------------
38
39using namespace os;
40
41// ----------------------------------------------------------------------------
42
47extern "C" void
48os_goodbye (void);
49
50namespace
51{
52 // --------------------------------------------------------------------------
53
54 // Since the native threads have a single argument, and it is better to
55 // avoid C++11 tuples and function objects, there is no other simple
56 // way than to pack the args in a structure and use it by the
57 // trampoline to invoke the os_main().
58
59#pragma GCC diagnostic push
60#pragma GCC diagnostic ignored "-Wpadded"
61
62 using main_args_t = struct
63 {
64 int argc;
65 char** argv;
66 };
67
68#pragma GCC diagnostic pop
69
70 static main_args_t main_args;
71
72 // --------------------------------------------------------------------------
73
74 [[noreturn]] static void
75 _main_trampoline (void)
76 {
77 trace::puts ("");
78 trace::dump_args (main_args.argc, main_args.argv);
79
80 int code = os_main (main_args.argc, main_args.argv);
81 trace::printf ("%s() exit = %d\n", __func__, code);
82
83 // Exit will run the atexit() and destructors, then
84 // terminate gracefully.
85 std::exit (code);
86 }
87
88// --------------------------------------------------------------------------
89
90} /* namespace */
91
96// ----------------------------------------------------------------------------
98
99// Intentionally a raw pointer, to prevent destruction.
101
102#if defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
103
104// Necessarily static, on Cortex-M the reset stack will be used
105// as MSP for the interrupts, so the current stack must be freed
106// and os_main() shall run on its own stack.
108static std::aligned_storage<sizeof(main_thread), alignof(main_thread)>::type os_main_thread_;
109
110#endif /* defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
111
115int
116#if !defined(__APPLE__)
117__attribute__((weak))
118#endif
119main (int argc, char* argv[])
120{
121 using namespace os::rtos;
122
123 trace::printf ("\nµOS++ IIIe version " OS_STRING_RTOS_IMPL_VERSION ".\n");
124 trace::printf ("Copyright (c) 2007-" OS_STRING_RTOS_IMPL_YEAR " Liviu Ionescu.\n");
125
126 port::scheduler::greeting ();
127
128 trace::printf ("Scheduler frequency: %u ticks/sec.\n",
130 trace::printf ("Default stack size: %u bytes.\n",
131 thread::stack::default_size ());
132#if defined(OS_HAS_INTERRUPTS_STACK)
133 trace::printf ("Interrupts stack size: %u bytes.\n",
134 interrupts::stack ()->size ());
135#endif /* defined(OS_HAS_INTERRUPTS_STACK) */
136
137#if defined(__clang__)
138 trace::printf ("Built with clang " __VERSION__);
139#else
140 trace::printf ("Built with GCC " __VERSION__);
141#endif
142
143#if defined(__EXCEPTIONS)
144 trace::printf (", with exceptions");
145#else
146 trace::printf (", no exceptions");
147#endif
148 trace::puts (".\n");
149
150 scheduler::initialize ();
151
152 // Store the parameters in the static structure, to be used by os_main().
153 main_args.argc = argc;
154 main_args.argv = argv;
155
156#if defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
157
158 // Running the constructor manually has the additional advantage of
159 // not registering any destructor, and for main this is important,
160 // since the destructors are executed on its context, and it cannot
161 // destruct itself.
162 new (&os_main_thread_) main_thread
163 {"main", reinterpret_cast<thread::func_t> (_main_trampoline), nullptr};
164
165 os_main_thread = reinterpret_cast<rtos::thread*>(&os_main_thread_);
166
167#else
168
169 thread::attributes attr = thread::initializer;
171 os_main_thread = new thread (
172 "main", reinterpret_cast<thread::func_t> (_main_trampoline), nullptr,
173 attr);
174
175#endif /* defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
176
177#if !defined(OS_USE_RTOS_PORT_SCHEDULER)
179#endif /* !defined(OS_USE_RTOS_PORT_SCHEDULER) */
180
181 // Execution will proceed to first registered thread, possibly
182 // "idle", which will immediately lower its priority,
183 // and at a certain moment will reach os_main().
184 scheduler::start ();
185
186 /* NOTREACHED */
187}
188
189void
190#if !defined(__APPLE__)
191__attribute__((weak))
192#endif
194{
195#if defined(TRACE)
196
197 trace::printf ("\n");
198
199#if !defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS)
200
201 // Application memory.
203
204#if defined(OS_INTEGER_RTOS_DYNAMIC_MEMORY_SIZE_BYTES)
206#endif /* defined(OS_INTEGER_RTOS_DYNAMIC_MEMORY_SIZE_BYTES) */
207
208#endif /* !defined(OS_EXCLUDE_DYNAMIC_MEMORY_ALLOCATIONS) */
209
211
212 trace::printf ("Main thread stack: %u/%u bytes used\n",
213 st.size () - st.available (), st.size ());
214
215#if defined(OS_HAS_INTERRUPTS_STACK)
217 "Interrupts stack: %u/%u bytes used\n",
221#endif /* defined(OS_HAS_INTERRUPTS_STACK) */
222
223 trace::printf ("\nHasta la Vista!\n");
224
225#endif /* defined(TRACE) */
226}
227
228// ----------------------------------------------------------------------------
static constexpr uint32_t frequency_hz
SysTick frequency in Hz.
Definition os-clocks.h:480
void trace_print_statistics(void)
Print a long message with usage statistics.
Definition os-memory.h:1448
Thread attributes.
Definition os-thread.h:791
std::size_t th_stack_size_bytes
Size of the user defined storage for the thread stack, in bytes.
Definition os-thread.h:851
std::size_t size(void)
Get the stack size.
Definition os-thread.h:2162
std::size_t available(void)
Compute how much available stack remains.
Template of a POSIX compliant thread with local stack.
Definition os-thread.h:1816
POSIX compliant thread, using the default RTOS allocator.
Definition os-thread.h:247
void *(*)(func_args_t args) func_t
Type of thread function.
Definition os-thread.h:417
class thread::stack & stack(void)
Get the thread context stack.
Definition os-thread.h:2438
Standard thread.
void os_goodbye(void)
#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_terminate_goodbye(void)
Display statistics and say goodbye before terminating.
Definition os-main.cpp:193
int puts(const char *s)
Write the string and a line terminator to the trace device.
Definition trace.cpp:108
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:74
void dump_args(int argc, char *argv[])
Write the argv[] array to the trace device.
Definition trace.cpp:140
int os_main(int argc, char *argv[])
Application entry point, running on the main thread context.
class thread::stack * stack(void)
Get the interrupts stack.
Definition os-core.cpp:564
memory_resource * get_default_resource(void) noexcept
Get the default RTOS system memory manager.
Definition os-memory.h:1137
memory_resource * get_default_resource(void) noexcept
Get the default application memory manager.
RTOS namespace.
Definition os-flags.h:54
System namespace.
int main(int argc, char *argv[])
Default implementation of main().
Definition os-main.cpp:119
rtos::thread * os_main_thread
Definition os-main.cpp:100
#define OS_STRING_RTOS_IMPL_YEAR
Definition os-versions.h:58
#define OS_STRING_RTOS_IMPL_VERSION
Definition os-versions.h:60
Single file µOS++ RTOS definitions.