Commit | Line | Data |
---|---|---|
93ea6adb JM |
1 | /* |
2 | This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl). | |
3 | Smoothie 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 3 of the License, or (at your option) any later version. | |
4 | Smoothie 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. | |
5 | You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>. | |
6 | */ | |
7 | ||
8 | /** | |
9 | This is aprt of the Smoothie test framework, it generates a Mockable Kernl so kernel calls can be tested for | |
10 | */ | |
11 | ||
12 | #include "libs/Kernel.h" | |
13 | #include "libs/Module.h" | |
14 | #include "libs/Config.h" | |
15 | #include "libs/nuts_bolts.h" | |
16 | #include "libs/SlowTicker.h" | |
17 | #include "libs/Adc.h" | |
18 | #include "libs/StreamOutputPool.h" | |
19 | #include <mri.h> | |
20 | #include "checksumm.h" | |
21 | #include "ConfigValue.h" | |
22 | ||
23 | #include "libs/StepTicker.h" | |
24 | #include "libs/PublicData.h" | |
25 | #include "modules/communication/SerialConsole.h" | |
26 | #include "modules/communication/GcodeDispatch.h" | |
27 | #include "modules/robot/Planner.h" | |
28 | #include "modules/robot/Robot.h" | |
29 | #include "modules/robot/Stepper.h" | |
30 | #include "modules/robot/Conveyor.h" | |
93ea6adb JM |
31 | |
32 | #include "Config.h" | |
33 | #include "FirmConfigSource.h" | |
34 | ||
35 | #include <malloc.h> | |
36 | #include <array> | |
37 | #include <functional> | |
38 | #include <map> | |
39 | ||
40 | Kernel* Kernel::instance; | |
41 | ||
42 | // The kernel is the central point in Smoothie : it stores modules, and handles event calls | |
43 | Kernel::Kernel(){ | |
44 | instance= this; // setup the Singleton instance of the kernel | |
45 | ||
46 | // serial first at fixed baud rate (DEFAULT_SERIAL_BAUD_RATE) so config can report errors to serial | |
47 | // Set to UART0, this will be changed to use the same UART as MRI if it's enabled | |
48 | this->serial = new SerialConsole(USBTX, USBRX, DEFAULT_SERIAL_BAUD_RATE); | |
49 | ||
50 | // Config next, but does not load cache yet | |
51 | // loads config from in memory source for test framework must be loaded by test | |
52 | this->config = nullptr; | |
53 | ||
54 | this->streams = new StreamOutputPool(); | |
55 | this->streams->append_stream(this->serial); | |
56 | ||
57 | this->current_path = "/"; | |
58 | ||
2097978f JM |
59 | this->slow_ticker = new SlowTicker(); |
60 | ||
a3cb0c4c | 61 | // dummies (would be nice to refactor to not have to create a conveyor) |
2097978f JM |
62 | this->conveyor= new Conveyor(); |
63 | ||
93ea6adb JM |
64 | // Configure UART depending on MRI config |
65 | // Match up the SerialConsole to MRI UART. This makes it easy to use only one UART for both debug and actual commands. | |
66 | NVIC_SetPriorityGrouping(0); | |
67 | NVIC_SetPriority(UART0_IRQn, 5); | |
68 | } | |
69 | ||
70 | // Add a module to Kernel. We don't actually hold a list of modules we just call its on_module_loaded | |
71 | void Kernel::add_module(Module* module){ | |
72 | module->on_module_loaded(); | |
73 | } | |
74 | ||
75 | // Adds a hook for a given module and event | |
76 | void Kernel::register_for_event(_EVENT_ENUM id_event, Module *mod){ | |
77 | this->hooks[id_event].push_back(mod); | |
78 | } | |
79 | ||
80 | static std::map<_EVENT_ENUM, std::function<void(void*)> > event_callbacks; | |
81 | ||
82 | // Call a specific event with an argument | |
83 | void Kernel::call_event(_EVENT_ENUM id_event, void * argument){ | |
84 | for (auto m : hooks[id_event]) { | |
85 | (m->*kernel_callback_functions[id_event])(argument); | |
86 | } | |
87 | if(event_callbacks.find(id_event) != event_callbacks.end()){ | |
88 | event_callbacks[id_event](argument); | |
89 | }else{ | |
90 | printf("call_event for event: %d not handled\n", id_event); | |
91 | } | |
92 | } | |
93 | ||
94 | // These are used by tests to test for various things. basically mocks | |
95 | bool Kernel::kernel_has_event(_EVENT_ENUM id_event, Module *mod) | |
96 | { | |
97 | for (auto m : hooks[id_event]) { | |
98 | if(m == mod) return true; | |
99 | } | |
100 | return false; | |
101 | } | |
102 | ||
103 | void Kernel::unregister_for_event(_EVENT_ENUM id_event, Module *mod) | |
104 | { | |
105 | for (auto i = hooks[id_event].begin(); i != hooks[id_event].end(); ++i) { | |
106 | if(*i == mod) { | |
107 | hooks[id_event].erase(i); | |
108 | return; | |
109 | } | |
110 | } | |
111 | } | |
112 | ||
113 | void test_kernel_setup_config(const char* start, const char* end) | |
114 | { | |
115 | THEKERNEL->config= new Config(new FirmConfigSource("rom", start, end) ); | |
116 | // Pre-load the config cache | |
117 | THEKERNEL->config->config_cache_load(); | |
118 | } | |
119 | ||
120 | void test_kernel_teardown() | |
121 | { | |
122 | delete THEKERNEL->config; | |
123 | THEKERNEL->config= nullptr; | |
124 | event_callbacks.clear(); | |
125 | } | |
126 | ||
127 | void test_kernel_trap_event(_EVENT_ENUM id_event, std::function<void(void*)> fnc) | |
128 | { | |
129 | event_callbacks[id_event]= fnc; | |
130 | } | |
131 | ||
132 | void test_kernel_untrap_event(_EVENT_ENUM id_event) | |
133 | { | |
134 | event_callbacks.erase(id_event); | |
135 | } |