Browse Source

now it's possible to read and write SYSTEM.INI using bulk

Ondřej Hruška 1 year ago
parent
commit
9182c666ea
Signed by: Ondřej Hruška <ondra@ondrovo.com> GPG key ID: 2C5FD5035250423D
6 changed files with 181 additions and 68 deletions
  1. 53 45
      comm/interfaces.c
  2. 33 14
      comm/messages.c
  3. 37 9
      framework/system_settings.c
  4. 3 0
      framework/system_settings.h
  5. 43 0
      platform/cfg_utils.c
  6. 12 0
      platform/cfg_utils.h

+ 53 - 45
comm/interfaces.c View File

@@ -18,7 +18,7 @@ enum ComportSelection gActiveComport = COMPORT_USB; // start with USB so the han
18 18
 static uint32_t last_switch_time = 0; // started with USB
19 19
 static bool xfer_verify_done = false;
20 20
 
21
-static void configure_interface(enum ComportSelection iface);
21
+static bool configure_interface(enum ComportSelection iface);
22 22
 
23 23
 /** Switch com transfer if the current one doesnt seem to work */
24 24
 void com_switch_transfer_if_needed(void)
@@ -30,8 +30,8 @@ void com_switch_transfer_if_needed(void)
30 30
 
31 31
     if (gActiveComport == COMPORT_USB) {
32 32
         if (elapsed > 1000) {
33
-            // USB may or may not work, depending on whether the module is plugged -
34
-            // in or running from a battery/external supply remotely.
33
+            // USB may or may not work, depending on whether the module is plugged in
34
+            // or running from a battery/external supply remotely.
35 35
 
36 36
             // Check if USB is enumerated
37 37
 
@@ -39,19 +39,30 @@ void com_switch_transfer_if_needed(void)
39 39
             if (0 == uadr) {
40 40
                 dbg("Not enumerated, assuming USB is dead");
41 41
 
42
-                // Fallback to bare USART
43
-                if (SystemSettings.use_comm_uart) {
44
-                    configure_interface(COMPORT_USART);
45
-                }
46
-                else if (SystemSettings.use_comm_nordic) {
47
-                    configure_interface(COMPORT_NORDIC); // this fallbacks to LoRa if LoRa enabled
48
-                }
49
-                else if (SystemSettings.use_comm_lora) {
50
-                    configure_interface(COMPORT_LORA);
51
-                }
52
-                else {
53
-                    dbg("No alternate com interface configured, leaving USB enabled.");
54
-                }
42
+                // Fallback to radio or bare USART
43
+                do {
44
+                    if (SystemSettings.use_comm_nordic) {
45
+                        if (configure_interface(COMPORT_NORDIC)) {
46
+                            break;
47
+                        }
48
+                    }
49
+
50
+                    if (SystemSettings.use_comm_lora) {
51
+                        if (configure_interface(COMPORT_LORA)) {
52
+                            break;
53
+                        }
54
+                    }
55
+
56
+                    if (SystemSettings.use_comm_uart) {
57
+                        // after nordic/lora
58
+                        if (configure_interface(COMPORT_USART)) {
59
+                            break;
60
+                        }
61
+                    }
62
+
63
+                    dbg("No alternate com interface configured.");
64
+                    gActiveComport = COMPORT_NONE;
65
+                } while (0);
55 66
             } else {
56 67
                 dbg("USB got address 0x%02x - OK", (int)uadr);
57 68
             }
@@ -131,7 +142,7 @@ void com_iface_flush_buffer(void)
131 142
     }
132 143
 }
133 144
 
134
-static void configure_interface(enum ComportSelection iface)
145
+static bool configure_interface(enum ComportSelection iface)
135 146
 {
136 147
     // Teardown
137 148
     if (gActiveComport == COMPORT_USB) {
@@ -146,11 +157,17 @@ static void configure_interface(enum ComportSelection iface)
146 157
         __HAL_RCC_USART2_CLK_DISABLE();
147 158
         irqd_detach(USART2, com_UsartIrqHandler);
148 159
     }
149
-    gActiveComport = COMPORT_NONE;
160
+    else if (gActiveComport == COMPORT_NORDIC) {
161
+        // TODO
162
+    }
163
+
164
+
165
+    gActiveComport = iface;
150 166
 
151 167
     // Init
152 168
     if (iface == COMPORT_USB) {
153 169
         trap("illegal"); // this never happens
170
+        return false;
154 171
     }
155 172
     else if (iface == COMPORT_USART) {
156 173
         dbg("Setting up UART transfer");
@@ -171,37 +188,28 @@ static void configure_interface(enum ComportSelection iface)
171 188
         LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX);
172 189
 
173 190
         LL_USART_Enable(USART2);
174
-    }
175
-    else {
176
-        if (iface == COMPORT_NORDIC) {
177
-            // Try to configure nordic
178
-            dbg("Setting up nRF transfer");
179
-
180
-            // TODO set up and check nRF transport
181 191
 
182
-            // On failure, try setting up LoRa
183
-            dbg("nRF failed to init");
184
-            if (SystemSettings.use_comm_lora) {
185
-                iface = COMPORT_LORA;
186
-            } else {
187
-                iface = COMPORT_NONE; // fail
188
-            }
189
-        }
192
+        return true; // always OK (TODO check voltage on Rx if it's 3V3 when idle?)
193
+    }
194
+    else if (iface == COMPORT_NORDIC) {
195
+        // Try to configure nordic
196
+        dbg("Setting up nRF transfer");
190 197
 
191
-        if (iface == COMPORT_LORA) {
192
-            // Try to configure nordic
193
-            dbg("Setting up LoRa transfer");
198
+        // TODO set up and check nRF transport
194 199
 
195
-            // TODO set up and check LoRa transport
196 200
 
197
-            dbg("LoRa failed to init");
198
-            iface = COMPORT_NONE; // fail
199
-        }
201
+        // On failure, try setting up LoRa
202
+        dbg("nRF failed to init");
203
+        return false;
200 204
     }
201
-
202
-    if (iface == COMPORT_NONE) {
203
-        dbg("NO COM PORT AVAILABLE!");
205
+    else if (iface == COMPORT_LORA) {
206
+        // Try to configure nordic
207
+        dbg("Setting up LoRa transfer");
208
+        // TODO set up and check LoRa transport
209
+        dbg("LoRa failed to init");
210
+        return false;
211
+    }
212
+    else {
213
+        trap("Bad iface %d", iface);
204 214
     }
205
-
206
-    gActiveComport = iface;
207 215
 }

+ 33 - 14
comm/messages.c View File

@@ -58,26 +58,33 @@ static TF_Result lst_list_units(TinyFrame *tf, TF_Msg *msg)
58 58
 
59 59
 // ---------------------------------------------------------------------------
60 60
 
61
-/** Callback for bulk read of the settings file */
62
-static void settings_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer)
61
+/** Callback for bulk read of a settings file */
62
+static void ini_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer)
63 63
 {
64 64
     // clean-up request
65 65
     if (buffer == NULL) {
66 66
         free_ck(bulk);
67 67
         iw_end();
68
-//        dbg("INI read complete.");
69 68
         return;
70 69
     }
71 70
 
72 71
     if (bulk->offset == 0) iw_begin();
73 72
 
74 73
     IniWriter iw = iw_init((char *)buffer, bulk->offset, chunk);
75
-    iw.tag = 1;
76
-    settings_build_units_ini(&iw);
74
+    iw.tag = 1; // indicates this is read via the API (affects some comments)
75
+
76
+    uint8_t filenum = (uint8_t) (int) bulk->userdata;
77
+    
78
+    if (filenum == 0) {
79
+        settings_build_units_ini(&iw);
80
+    }
81
+    else if (filenum == 1) {
82
+        settings_build_system_ini(&iw);
83
+    }
77 84
 }
78 85
 
79 86
 /**
80
- * Listener: Export INI file via TF
87
+ * Listener: Export a file via TF
81 88
  */
82 89
 static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
83 90
 {
@@ -86,14 +93,29 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
86 93
     BulkRead *bulk = malloc_ck(sizeof(BulkRead));
87 94
     assert_param(bulk != NULL);
88 95
 
96
+    uint8_t filenum = 0;
97
+
98
+    // if any payload, the first byte defines the file to read
99
+    // 0 - units
100
+    // 1 - system
101
+    // (this is optional for backwards compatibility)
102
+    if (msg->len > 0) {
103
+        filenum = msg->data[0];
104
+    }
105
+
89 106
     bulk->frame_id = msg->frame_id;
90
-    bulk->len = iw_measure_total(settings_build_units_ini, 1);
91
-    bulk->read = settings_bulkread_cb;
92
-    bulk->userdata = NULL;
107
+    bulk->read = ini_bulkread_cb;
108
+    bulk->userdata = (void *) (int)filenum;
109
+
110
+    if (filenum == 0) {
111
+        bulk->len = iw_measure_total(settings_build_units_ini, 1);
112
+    }
113
+    else if (filenum == 1) {
114
+        bulk->len = iw_measure_total(settings_build_system_ini, 1);
115
+    }
93 116
 
94 117
     bulkread_start(tf, bulk);
95 118
     Indicator_Effect(STATUS_DISK_BUSY_SHORT);
96
-
97 119
     return TF_STAY;
98 120
 }
99 121
 
@@ -142,7 +164,7 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
142 164
     PayloadParser pp = pp_start(msg->data, msg->len, NULL);
143 165
     uint32_t len = pp_u32(&pp);
144 166
     if (!pp.ok) {
145
-        com_respond_error(msg->frame_id, E_PROTOCOL_BREACH);
167
+        com_respond_error(msg->frame_id, E_MALFORMED_COMMAND);
146 168
         goto done;
147 169
     }
148 170
 
@@ -151,11 +173,8 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
151 173
 
152 174
     settings_load_ini_begin();
153 175
     ini_parse_begin(iniparser_cb, NULL);
154
-
155 176
     bulkwrite_start(tf, bulk);
156
-
157 177
     Indicator_Effect(STATUS_DISK_BUSY);
158
-
159 178
 done:
160 179
     return TF_STAY;
161 180
 }

+ 37 - 9
framework/system_settings.c View File

@@ -2,8 +2,6 @@
2 2
 // Created by MightyPork on 2017/12/02.
3 3
 //
4 4
 
5
-#include <platform/debug_uart.h>
6
-#include <comm/interfaces.h>
7 5
 #include "platform.h"
8 6
 #include "system_settings.h"
9 7
 #include "utils/str_utils.h"
@@ -11,6 +9,8 @@
11 9
 #include "cfg_utils.h"
12 10
 #include "resources.h"
13 11
 #include "unit_base.h"
12
+#include "platform/debug_uart.h"
13
+#include "comm/interfaces.h"
14 14
 
15 15
 static void systemsettings_mco_teardown(void);
16 16
 static void systemsettings_mco_init(void);
@@ -171,18 +171,34 @@ void systemsettings_build_ini(IniWriter *iw)
171 171
     iw_entry_d(iw, "mco-prediv", (1<<SystemSettings.mco_prediv));
172 172
 
173 173
     iw_cmt_newline(iw);
174
-    iw_comment(iw, "Allowed fallback communication ports");
174
+    iw_comment(iw, "--- Allowed fallback communication ports ---");
175 175
 
176
-    iw_comment(iw, "UART Tx:PA2, Rx:PA2");
176
+    iw_cmt_newline(iw);
177
+    iw_comment(iw, "UART Tx:PA2, Rx:PA3");
177 178
     iw_entry_s(iw, "com-uart", str_yn(SystemSettings.use_comm_uart));
178 179
     iw_entry_d(iw, "com-uart-baud", SystemSettings.comm_uart_baud);
179 180
 
181
+    iw_cmt_newline(iw);
182
+    iw_comment(iw, "nRF24L01+ radio");
183
+    iw_entry_s(iw, "com-nrf", str_yn(SystemSettings.use_comm_nordic));
184
+
185
+    iw_comment(iw, "nRF channel");
186
+    iw_entry_d(iw, "nrf-channel", SystemSettings.nrf_channel);
187
+
188
+    iw_comment(iw, "nRF network ID (hex, 4 bytes, little-endian)");
189
+    iw_entry(iw, "nrf-network", "%02X.%02X.%02X.%02X",
190
+             SystemSettings.nrf_network[0],
191
+             SystemSettings.nrf_network[1],
192
+             SystemSettings.nrf_network[2],
193
+             SystemSettings.nrf_network[3]);
194
+
195
+    iw_comment(iw, "nRF node address (hex, 1 byte, > 0)");
196
+    iw_entry(iw, "nrf-address", "%02X",
197
+             SystemSettings.nrf_address);
198
+
180 199
     // those aren't implement yet, don't tease the user
181 200
     // TODO show pin-out, extra settings if applicable
182 201
 #if 0
183
-    iw_comment(iw, "nRF24L01+");
184
-    iw_entry_s(iw, "com-nordic", str_yn(SystemSettings.use_comm_nrf24l01p));
185
-
186 202
     iw_comment(iw, "LoRa/GFSK sx127x");
187 203
     iw_entry_s(iw, "com-lora", str_yn(SystemSettings.use_comm_sx127x));
188 204
 #endif
@@ -241,12 +257,24 @@ bool systemsettings_load_ini(const char *restrict key, const char *restrict valu
241 257
         if (suc) SystemSettings.comm_uart_baud = baud;
242 258
     }
243 259
 
244
-#if 0
245
-    if (streq(key, "com-nordic")) {
260
+    if (streq(key, "com-nrf")) {
246 261
         bool yn = cfg_bool_parse(value, &suc);
247 262
         if (suc) SystemSettings.use_comm_nordic = yn;
248 263
     }
249 264
 
265
+    if (streq(key, "nrf-channel")) {
266
+        SystemSettings.nrf_channel = cfg_u8_parse(value, &suc);
267
+    }
268
+
269
+    if (streq(key, "nrf-address")) {
270
+        cfg_hex_parse(&SystemSettings.nrf_address, 1, value, &suc);
271
+    }
272
+
273
+    if (streq(key, "nrf-network")) {
274
+        cfg_hex_parse(&SystemSettings.nrf_network[0], 4, value, &suc);
275
+    }
276
+
277
+#if 0
250 278
     if (streq(key, "com-lora")) {
251 279
         bool yn = cfg_bool_parse(value, &suc);
252 280
         if (suc) SystemSettings.use_comm_lora = yn;

+ 3 - 0
framework/system_settings.h View File

@@ -27,6 +27,9 @@ struct system_settings {
27 27
     uint32_t comm_uart_baud; // baud rate for the uart transport
28 28
     bool use_comm_lora;   // SX1276/8
29 29
     bool use_comm_nordic; // nRF24L01+
30
+    uint8_t nrf_channel;
31
+    uint8_t nrf_network[4];
32
+    uint8_t nrf_address;
30 33
 
31 34
     // Support flags put here for scoping, but not atcually part of the persistent settings
32 35
     volatile bool editable; //!< True if we booted with the LOCK jumper removed

+ 43 - 0
platform/cfg_utils.c View File

@@ -297,3 +297,46 @@ uint32_t cfg_enum4_parse(const char *value,
297 297
     *suc = false;
298 298
     return na;
299 299
 }
300
+
301
+void cfg_hex_parse(uint8_t *dest, uint32_t count, const char *value, bool *suc)
302
+{
303
+    // discard possible leading 0x
304
+    if (value[0] == '0' && value[1] == 'x') {
305
+        value += 2;
306
+    }
307
+
308
+    uint8_t bytebuf = 0;
309
+    for (uint32_t digit = 0; digit < count * 2;) {
310
+        char v = *value;
311
+        if (v != 0) value++;
312
+
313
+        uint8_t nibble = 0;
314
+        if (v == ' ' || v == '.' || v == '-' || v == ':') {
315
+            continue; // junk
316
+        }
317
+        else if (v >= '0' && v <= '9') {
318
+            nibble = (uint8_t) (v - '0');
319
+        }
320
+        else if (v >= 'a' && v <= 'f') {
321
+            nibble = (uint8_t) (10 + (v - 'a'));
322
+        }
323
+        else if (v >= 'A' && v <= 'F') {
324
+            nibble = (uint8_t) (10 + (v - 'A'));
325
+        }
326
+        else if (v == 0) {
327
+            nibble = 0; // pad with zeros
328
+        }
329
+        else {
330
+            *suc = false;
331
+            return;
332
+        }
333
+
334
+        digit++;
335
+        bytebuf <<= 4;
336
+        bytebuf |= nibble;
337
+        if ((digit % 2 == 0) && digit > 0) { // whole byte
338
+            *dest++ = bytebuf;
339
+            bytebuf = 0;
340
+        }
341
+    }
342
+}

+ 12 - 0
platform/cfg_utils.h View File

@@ -116,6 +116,18 @@ uint32_t cfg_enum4_parse(const char *tpl,
116 116
                          const char *d, uint32_t nd,
117 117
                          bool *suc);
118 118
 
119
+/**
120
+ * Parse a hexa string to a byte array.
121
+ * Skips 0x prefix, '.', '-', ':', ' '.
122
+ *
123
+ * @param[out] dest - storage array
124
+ * @param[in] count - expected number of bytes
125
+ * @param[in] value - parsed string
126
+ * @param[out] suc - success flag
127
+ */
128
+void cfg_hex_parse(uint8_t *dest, uint32_t count,
129
+                   const char *value, bool *suc);
130
+
119 131
 /** Convert bool to a Y or N constant string */
120 132
 #define str_yn(cond) ((cond) ? ("Y") : ("N"))
121 133