66#define RESET_METHOD " $/reset"
77#define BIND_METHOD " $/register"
88
9+ #include < zephyr/kernel.h>
910#include < Arduino_RPClite.h>
1011
1112
@@ -15,14 +16,22 @@ class Bridge {
1516 RPCServer* server = nullptr ;
1617 ITransport* transport;
1718
19+ struct k_mutex read_mutex;
20+ struct k_mutex write_mutex;
21+
1822public:
1923 Bridge (ITransport& t) : transport(&t) {}
24+
2025 Bridge (Stream& stream) {
2126 transport = new SerialTransport (stream);
2227 }
2328
2429 // Initialize the bridge
2530 bool begin () {
31+
32+ k_mutex_init (&read_mutex);
33+ k_mutex_init (&write_mutex);
34+
2635 client = new RPCClient (*transport);
2736 server = new RPCServer (*transport);
2837 bool res;
@@ -38,19 +47,60 @@ class Bridge {
3847 return server->bind (name, func);
3948 }
4049
50+ template <typename F>
51+ bool provide_safe (const MsgPack::str_t & name, F&& func) {
52+ bool res;
53+ if (!call (BIND_METHOD, res, name)) {
54+ return false ;
55+ }
56+
57+ return server->bind (name, func, " __safe__" );
58+
59+ }
60+
4161 void update () {
42- // Protect the following calls with a mutex if necessary
43- // server->read_request(); // <- inbound
44- // server->serve(); // -> outbound
45- server->run ();
62+
63+ // Lock read mutex
64+ while (1 ){
65+ k_mutex_lock (&read_mutex, K_FOREVER);
66+ if (server->get_rpc ()) {
67+ k_mutex_unlock (&read_mutex);
68+ break ;
69+ }
70+ k_mutex_unlock (&read_mutex);
71+ k_msleep (1 );
72+ }
73+
74+ server->process_request ();
75+
76+ // Lock write mutex
77+ k_mutex_lock (&write_mutex, K_FOREVER);
78+ server->send_response ();
79+ k_mutex_unlock (&write_mutex);
80+
4681 }
4782
4883 template <typename RType, typename ... Args>
4984 bool call (const MsgPack::str_t method, RType& result, Args&&... args) {
50- // Protect the following calls with a mutex if necessary
51- // client->send_call(); // -> outbound
52- // client->read_response(); // <- inbound
53- return client->call (method, result, std::forward<Args>(args)...);
85+
86+ // Lock write mutex
87+ k_mutex_lock (&write_mutex, K_FOREVER);
88+ client->send_rpc (method, std::forward<Args>(args)...);
89+ k_mutex_unlock (&write_mutex);
90+
91+ // Lock read mutex
92+ while (1 ) {
93+ k_mutex_lock (&read_mutex, K_FOREVER);
94+ if (client->get_response (result)) {
95+ k_mutex_unlock (&read_mutex);
96+ break ;
97+ }
98+ k_mutex_unlock (&read_mutex);
99+ k_msleep (1 );
100+ }
101+
102+ return (client->lastError .code == NO_ERR);
103+
54104 }
55105
56106 template <typename ... Args>
@@ -66,6 +116,52 @@ class Bridge {
66116 return (uint8_t ) client->lastError .code ;
67117 }
68118
119+ private:
120+
121+ void update_safe () {
122+
123+ // Lock read mutex
124+ while (1 ){
125+ k_mutex_lock (&read_mutex, K_FOREVER);
126+ if (server->get_rpc ()) {
127+ k_mutex_unlock (&read_mutex);
128+ break ;
129+ }
130+ k_mutex_unlock (&read_mutex);
131+ k_msleep (1 );
132+ }
133+
134+ server->process_request (" __safe__" );
135+
136+ // Lock write mutex
137+ k_mutex_lock (&write_mutex, K_FOREVER);
138+ server->send_response ();
139+ k_mutex_unlock (&write_mutex);
140+
141+ }
142+
143+ friend class BridgeUpdater ;
144+
69145};
70146
147+ class BridgeUpdater {
148+ public:
149+ static void safeUpdate (Bridge& bridge) {
150+ bridge.update_safe (); // access private method
151+ }
152+
153+ private:
154+ BridgeUpdater () = delete ; // prevents instantiation
155+ };
156+
157+ Bridge BRIDGE (Serial1);
158+
159+ static void safeUpdate (){
160+ BridgeUpdater::safeUpdate (BRIDGE);
161+ }
162+
163+ void __loopHook (){
164+ safeUpdate ();
165+ }
166+
71167#endif // BRIDGE_IMOLA_H
0 commit comments