SingingCat 0
application
user_app_exe.c
Go to the documentation of this file.
1#include "user_app_exe.h"
2#include "main-header.h"
3#include "sys/types.h"
4#include "user_app_info.h"
5#include "powersave.h"
6#include "constants.h"
7#include "config.h"
8#include "command-parser.h"
9#include "sensors/sensor.h"
10#include "ascii_parser.h"
11#include "led.h"
12#include "userconfig.h"
13#include "protobuf.h"
14#include "fets.h"
15#include "sc_time.h"
16#include "softirq.h"
17#include "api_version.h"
18#include "hijack.h"
19#include "reboot.h"
20static uint32_t repoid; // most recently started repoid (e.g. for printf)
21static uint32_t version; // most recently started version (e.g. for printf)
22static struct command *alloc_command_user();
23static int user_serialport_callback(int mculibhandle, int portnum, serial_recv_callback cb);
24static int mcu_set_speed(int mculibhandle, int speed);
25static void reset_userapp();
26static void led_app_blink(int colour, int brightness, int on, int off);
31static int register_user_sensor(struct sensordev *sensor);
32static void free_user_sensors();
33static struct sensordev *sensordevptr[20];
34static int unhandled_call();
35static void user_printf(const char *format, ...);
36static void user_debugf(const char *format, ...);
37static serial_recv_callback serial_recv_callback_usart3;
38static char userappbuf[500]; // max 512 lines long please
39static char *PREFIX = "userapp";
46static struct sc_firmware_api user_callback_api = {
47 .printf = &user_printf,
48 .debugf = &user_debugf,
49 .mculib_serialport_enable = &mculib_serialport_enable,
50 .mculib_serialport_disable = &mculib_serialport_disable,
51 .user_serialport_callback = &user_serialport_callback,
52 .mculib_serialport_write_char = &mculib_serialport_write_char,
53 .mculib_pin_out = &mculib_pin_out,
54 .mculib_pin_out_opendrain = &mculib_pin_out_opendrain,
55 .mculib_pin_in = &mculib_pin_in,
56 .mculib_pin_in_callback = &mculib_pin_in_callback,
57 .mculib_pin_set = &mculib_pin_set,
58 .mculib_pin_release = &mculib_pin_release,
59 .mculib_pin_get = &mculib_pin_get,
60 .mculib_serialport_write_string = &mculib_serialport_write_string,
61 .mculib_has_time_passed = &mculib_has_time_passed,
62 .mculib_get_seconds_since_boot = &mculib_get_seconds_since_boot,
63 .mculib_spi_disable = &mculib_spi_disable,
64 .mculib_spi_send_dma = &mculib_spi_send_dma,
65 .mculib_spi_speed = &mculib_spi_speed,
66 .mculib_spi_master_enable3 = &mculib_spi_master_enable3,
67 .mculib_spi_write_and_read = &mculib_spi_write_and_read,
68 .mculib_spi_write_only = &mculib_spi_write_only,
69 .mculib_spi_read16_only = &mculib_spi_read16_only,
70 .mculib_timer_enable_simple = &mculib_timer_enable_simple,
71 .mculib_timer_disable = &mculib_timer_disable,
72 .mculib_timer_attach_pin_pwm = &mculib_timer_attach_pin_pwm,
73 .mculib_timer_set_pwm = &mculib_timer_set_pwm,
74 .mculib_adc_read_once = &mculib_adc_read_once,
75 .mculib_adc_get_resolution = &mculib_adc_get_resolution,
76 .mculib_adc_enable = &mculib_adc_enable,
77 .mculib_adc_read = &mculib_adc_read,
78 .com_get_named_arg = &namedarg,
79 .com_get_named_arg_uint16 = &namedarg_uint16,
80 .com_get_named_arg_uint32 = &namedarg_uint32,
81 .com_get_arg = &get_arg,
82 .com_get_arg_size = &get_arg_size,
83 .com_add_arg = &command_add_arg,
84 .com_add_binary_arg = &command_add_binary_arg,
85 .com_add_varg = &command_add_varg,
86 .com_alloc = &alloc_command_user,
87 .com_free = &free_command,
88 .com_get_data_reply = &get_data_reply,
89 .com_send_reply_with_args = &send_command_reply_with_args,
90 .com_deliver_command = &deliver_command,
91 .sensor_register = &register_user_sensor,
92 .strcmp = &strcmp,
93 .memset = &memset,
94 .strlen = &strlen,
95 .strncpy = &strncpy,
96 .vsnprintf = &vsnprintf,
97 .snprintf = &snprintf,
98 .atoi = &atoi,
99 .led_blink = &led_app_blink,
100 .get_config_flag = &get_user_config_flag,
101 .com_send_command = &send_command,
102 .userconfig_size = &userconfig_size,
103 .userconfig_version = &userconfig_version,
104 .userconfig_copy = &userconfig_copy,
105 .userconfig_write = &userconfig_write,
106 .sensor_get_runtime_by_index = &get_runtime,
107 .proto_buf_to_struct = &buf_to_struct,
108 .proto_struct_to_buf = &struct_to_buf,
109 .proto_release = &proto_release,
110 .pin_pwm = &pin_pwm,
111 .time_get_localtime_as_struct = &get_localtime_as_struct,
112 .timer_softirq = &softirq_timer,
113 .time_get_diff = &diff_time,
114 .time_bcd_to_timestruct = &convert_timestamps_to_time,
115 .mcu_set_speed = &mcu_set_speed,
116 .hijack_usb_acm = &hijack_usb_acm,
117 .send_via_usb_acm = &send_via_usb_acm,
118 .hijack_esp32_usart = &hijack_esp32_usart,
119 .hijack_esp32_usart_stop = &unhijack_esp32,
120 .reset_module = &reboot_hard,
121 .reset_userapp = &reset_userapp,
122 .unhandled_call1 = &unhandled_call,
123 .unhandled_call2 = &unhandled_call,
124 .unhandled_call3 = &unhandled_call,
125 .unhandled_call4 = &unhandled_call,
126 .unhandled_call5 = &unhandled_call,
127 .unhandled_call6 = &unhandled_call,
128 .unhandled_call7 = &unhandled_call,
129 .unhandled_call8 = &unhandled_call,
130};
131
132
133/**************************** code to interact with usercode ************/
134
135static uint8_t crc_ok = 0; // 0: not checked, 1:ok, 2:false
136static uint8_t do_exe_user_app = 0;
137static uint8_t has_failed = 0;
138static uint8_t start_stop_status = 0; //most recent: 0->neither, 1->started, 2->stopped
139static uint32_t myversion = 0;
140static struct userapp_info *myapp;
141
142#define MCULIB_USERAPP_HANDLE 7
143
144// called by irq handlers and loop entry/exit
145void set_in_app(uint8_t a) {
146 constants()->in_user_app = a;
147}
148
149/* \brief called by main.c at startup, exactly once */
150void user_app_exe_init() {
151 memset(&sensordevptr, 0, sizeof(sensordevptr));
152 start_stop_status = 0;
153 myapp = (struct userapp_info *)config_get_userapp();
154 if (myapp != NULL) {
155 // store for later, so we can detect in-place upgrades
156 myversion = myapp->version;
157 }
158 crc_ok = 0;
159 /*
160 * was there a reset whilst userapp was executed?
161 */
162 if ((constants()->in_user_app) && (mculib_get_reset_source() != HAL_RESET_POWER)) {
163 has_failed = 1;
164 printf("Userapp disabled (fail-safe)\r\n");
165 } else {
166 has_failed = 0;
167 }
168}
169
170/*
171 * \brief return >0 if app has changed since we last called init()
172 */
173static int has_changed() {
174 struct userapp_info *newapp = (struct userapp_info *)config_get_userapp();
175
176 if (newapp != myapp) {
177 return 1;
178 }
179 if (newapp == NULL) {
180 return 0;
181 }
182 // current app and myapp are same and not NULL
183 if (newapp->version != myversion) {
184 return 1;
185 }
186 // add checksum/other tests here...
187 return 0;
188}
189
190static void reset_userapp() {
191 user_app_disable();
192 user_app_enable();
193}
194struct userapp_info *get_user_app() {
195 return myapp;
196}
197// return 1 if it is enabled
198int user_app_is_enabled() {
199 return do_exe_user_app;
200}
201/*
202 * \brief (re-)enable usercode. this is a bit more complex, because
203 * a) we must avoid calling start() twice and b) the userapp might have
204 * been upgraded since calling start().
205 * the userapp might been upgraded in-place or at another memory location.
206 * we detect in-place upgrade by comparing the version number
207 */
208void user_app_enable() {
209 do_exe_user_app = 1;
210 if (!user_app_executable()) {
211 return;
212 }
213 if ((has_changed()) && (start_stop_status == 1)) {
214 // stop old one
215 invoke_stop();
216 user_app_exe_init(); // re-init
217 }
218 if (start_stop_status != 1) {
219 invoke_start(MCULIB_USERAPP_HANDLE); // call the user startup hook (last thing to do)
220 mculib_print_mappings(&printf);
221 }
222}
223// TODO: clean up mculib
224void user_app_disable() {
225 if (!user_app_executable()) {
226 set_in_app(0);
227 do_exe_user_app = 0;
228 return;
229 }
230 do_exe_user_app = 0;
231 if (start_stop_status == 1) {
232 invoke_stop();
233 }
234 set_in_app(0);
235}
236// return != 0 if checksum is valid
237int user_app_checksum_valid() {
238 struct userapp_info *uai = get_user_app();
239
240 if (uai == NULL) {
241 return 0;
242 }
243
244 if (!has_changed()) {
245 if (crc_ok == 1) {
246 return 1;
247 } else if (crc_ok == 2) {
248 return 0;
249 }
250 }
251 if (!user_app_is_valid()) {
252 return 0;
253 }
254 uint32_t checksum = calc_crc32((void *)uai, uai->length, 8);
255
256 if (checksum == uai->checksum) {
257 crc_ok = 1;
258 return 1;
259 }
260 crc_ok = 2;
261 printf("Userapp checksum calculated: %p, reported: %p\r\n", checksum, uai->checksum);
262 return 0;
263}
264/* \brief returns !=0 if userapp is valid */
265int user_app_is_valid() {
266#ifdef __unix__
267 return 0;
268#endif
269
270 struct userapp_info *uai = get_user_app();
271 if (uai == NULL) {
272 return 0;
273 }
274 if (uai->magic != 0x53435541) {
275 return 0;
276 }
277
278 return 1;
279}
280
281/* \brief return !=0 if userapp should and can be executed */
282int user_app_executable() {
283#ifdef __unix__
284 return 0;
285#endif
286 if (has_failed) {
287 return 0;
288 }
289 if (!do_exe_user_app) {
290 return 0;
291 }
292 if (!user_app_is_valid()) {
293 return 0;
294 }
295 if (!user_app_checksum_valid()) {
296 return 0;
297 }
298
299 return 1;
300}
301
302void invoke_start(int MCULIBHANDLE) {
303 free_user_sensors();
304 set_in_app(1);
305 struct userapp_info *ua = get_user_app();
306
307 repoid = ua->repoid;
308 version = ua->version;
309 ua->start(MCULIBHANDLE, &user_callback_api);
310 set_in_app(0);
311 start_stop_status = 1;
312}
313void invoke_stop() {
314 serial_recv_callback_usart3 = NULL;
315 free_user_sensors();
316 softirqs_removeall();
317 set_in_app(1);
318 get_user_app()->stop();
319 unhijack_all();
320 set_in_app(0);
321 start_stop_status = 2;
322 led_off(LED_USER); // only turns it off if currently managed by user
323 mculib_release_by_handle(MCULIB_USERAPP_HANDLE);
324}
325int invoke_on_command_received(struct command *com) {
326 set_in_app(1);
327 int r = get_user_app()->on_command_received(com);
328
329 set_in_app(0);
330 return r;
331}
332void invoke_on_new_node(struct hostroute *host) {
333 set_in_app(1);
334 get_user_app()->on_new_node(host);
335 set_in_app(0);
336}
337
338void invoke_user_loop() {
339 set_in_app(1);
340 get_user_app()->user_loop();
341 set_in_app(0);
342}
343
344void user_app_reset_state() {
345 crc_ok = 0;
346 do_exe_user_app = 0;
347 myversion = 0;
348 set_in_app(0);
349 has_failed = 0;
350 unhijack_all();
351 printf("User app state reset\r\n");
352}
353
354// 0 if ok
355int send_user_app_status() {
356 return user_app_info(NULL);
357}
358static uint32_t user_app_git_repo() {
359 struct userapp_info *uac = get_user_app();
360
361 if (uac == NULL) {
362 return 0;
363 }
364 return uac->repoid;
365}
366static uint32_t user_app_timestamp() {
367 struct userapp_info *uac = get_user_app();
368
369 if (uac == NULL) {
370 return 0;
371 }
372 return uac->build_timestamp;
373}
374static uint32_t user_app_apiversion() {
375 struct userapp_info *uac = get_user_app();
376
377 if (uac == NULL) {
378 return 0;
379 }
380 return uac->api_version;
381}
382int user_app_info(struct command *com) {
383 struct command *reply = alloc_command();
384
385 if (reply == NULL) {
386 return 1;
387 }
388 printf("Delivering user_app_status\r\n");
389 reply->target = CLOUD_SERVER;
390 reply->com = 53; //userapp_info
391 command_add_arg(reply, "adr=%p", myapp);
392 command_add_arg(reply, "v=%p", myversion);
393 command_add_arg(reply, "f=%i", (int)has_failed);
394 command_add_arg(reply, "e=%i", user_app_executable());
395 command_add_arg(reply, "vl=%i", user_app_checksum_valid());
396 command_add_arg(reply, "en=%i", user_app_is_enabled());
397 command_add_arg(reply, "flags=%i", (uint32_t)get_user_config_flags());
398 command_add_arg(reply, "r=%i", user_app_git_repo());
399 command_add_arg(reply, "ts=%i", user_app_timestamp());
400 command_add_arg(reply, "av=%i/%i", user_app_apiversion(), CNW_API_VERSION);
401 reply->flags = COMFLAGS_SUCCESS;
402 reply->encoding = 'a';
403 if (com != NULL) {
404 reply->index = com->index;
405 reply->target = com->sender;
406 reply->flags = COMFLAGS_ACK | COMFLAGS_SUCCESS;
407 }
408 int i = deliver_command(reply, NULL);
409
410 if (i != 0) {
411 printf("Failed to deliver userapp_status command: %i\r\n", i);
412 }
413 return 0;
414}
415
416//userapp control command called
417void user_app_control(struct command *com) {
418 if (namedarg(com, "ucr") != NULL) {
419 int i = userconfig_receive(com);
420 if (i == 1) {
421 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
422 } else if (i == 2) {
423 send_command_reply(com, COMFLAGS_ACK);
424 }
425 return;
426 }
427 const char *x = get_arg(com, 0);
428
429 if (x == NULL) {
430 send_command_reply(com, COMFLAGS_ACK);
431 return;
432 }
433 int l = atoi(x);
434
435 if (l == 1) {
436 has_failed = 0;
437 user_app_enable();
438 } else if (l == 2) {
439 user_app_disable();
440 } else if (l == 3) {
441 // process flags and stuff later
442 } else {
443 printf("invalid userapp control: %i\r\n", l);
444 send_command_reply(com, COMFLAGS_ACK);
445 return;
446 }
447 x = namedarg(com, "flags");
448 if (x != NULL) {
449 uint32_t fl = atoi(x);
450 set_user_config_flags(fl);
451 }
452 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
453}
454
455/* led helper */
456static void led_app_blink(int colour, int brightness, int on, int off) {
457 led_set_user_managed();
458 led_blink(LED_USER, colour, brightness, on, off);
459}
460
461static void free_user_sensors() {
462 int max = sizeof(sensordevptr) / sizeof(struct sensordev *);
463 int i;
464
465 for (i = 0; i < max; i++) {
466 struct sensordev *entry = sensordevptr[i];
467 if (entry == NULL) {
468 continue;
469 }
470 sensor_deregister(entry);
471 sensordevptr[i] = NULL;
472 }
473}
474
475static int register_user_sensor(struct sensordev *sensor) {
476 struct sensordev *sd = sensor_register(sensor);
477
478 if (sd == 0) {
479 return 1;
480 }
481 int max = sizeof(sensordevptr) / sizeof(struct sensordev *);
482 int i;
483
484 for (i = 0; i < max; i++) {
485 struct sensordev *entry = sensordevptr[i];
486 if (entry == NULL) {
487 sensordevptr[i] = sd;
488 return 0;
489 }
490 }
491 return 2;
492}
493
494int userapp_checksum_valid(void *baseadr) {
495 struct userapp_info *uai = baseadr;
496
497 if (uai == NULL) {
498 return 0;
499 }
500 if (uai->magic != 0x53435541) {
501 return 0;
502 }
503
504 uint32_t checksum = calc_crc32((void *)uai, uai->length, 8);
505
506 if (checksum != uai->checksum) {
507 return 0;
508 }
509 return 1;
510}
511
512static void user_printf(const char *format, ...) {
513 va_list args;
514 int max_size = sizeof(userappbuf) - 1;
515
516 snprintf((char *)&userappbuf, max_size, "[%s info #%i/%i] ", PREFIX, repoid, version);
517
518 int l = strlen(userappbuf);
519
520 va_start(args, format);
521 vsnprintf((char *)&userappbuf + l, max_size - l, format, args);
522 va_end(args);
523 print((const char *)&userappbuf);
524}
525static void user_debugf(const char *format, ...) {
526 va_list args;
527 int max_size = 511;
528
529 snprintf((char *)&userappbuf, max_size, "[%s debug #%i/%i] ", PREFIX, repoid, version);
530
531 int l = strlen(userappbuf);
532
533 va_start(args, format);
534 vsnprintf((char *)&userappbuf + l, max_size - l, format, args);
535 va_end(args);
536 print((const char *)&userappbuf);
537}
538
539struct command *alloc_command_user() {
540 struct command *com = alloc_command_with_minfree(10);
541
542 return com;
543}
544
545static int unhandled_call() {
546 printf("Userapp called a function which is not implemented\r\n");
547 has_failed = 1;
548 user_app_disable();
549 return 0;
550}
551int user_serial_callback(int portnum, int byte) {
552 if (portnum != 3) {
553 return 0;
554 }
555 if (serial_recv_callback_usart3 == NULL) {
556 return 0;
557 }
558 serial_recv_callback_usart3(portnum, byte);
559 return 1;
560}
561static int user_serialport_callback(int mculibhandle, int portnum, serial_recv_callback cb) {
562 if (portnum != 3) {
563 return 5;
564 }
565 serial_recv_callback_usart3 = cb;
566 return 0;
567}
568static int mcu_set_speed(int mculibhandle, int speed) {
569 if (speed > 10) {
570 return 1;
571 }
572 if (speed < 0) {
573 return 2;
574 }
575 set_mcu_power_mode(speed);
576 return 0;
577}
int namedarg_uint16(struct command *com, const char *name, uint16_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
int send_command_reply_with_args(struct command *com, byte flags, const char *format,...)
send a reply to a command
Definition: queue.c:588
int send_command(struct command *com)
send a command to another module (or broadcast)
Definition: queue.c:374
void free_command(struct command *com)
free a command
Definition: queue.c:200
int deliver_command(struct command *com, pkt_callback)
deliver a command to a module
Definition: queue.c:651
void command_add_arg(struct command *com, const char *format,...)
adds an arg to a partially initialised command structure
const char * namedarg(struct command *com, const char *name)
get a named arg (key-value pair) or NULL
void command_add_varg(struct command *com, const char *format, va_list args)
adds a varg list of parameters to a command
int namedarg_uint32(struct command *com, const char *name, uint32_t *value)
get a named arg (key-value pair), parsed as integer. result in "value". if return value == 0 ,...
int send_command_reply(struct command *com, byte flags)
send a reply to a command
Definition: queue.c:562
struct command * get_data_reply(struct command *com)
allocates and initializes a packet to be send as "data" to the command typically you'd add some data ...
Definition: queue.c:271
struct command * alloc_command()
allocate a free command
Definition: queue.c:173
void led_blink(LED_USAGE_TYPE lut, uint32_t colour, uint8_t brightness, uint32_t on, uint32_t off)
will keep blinking until told otherwise will repeat endlessly.
Definition: led.c:288
int command_add_binary_arg(struct command *com, const int len, const byte *srcbuf)
adds a binary parameter to command returns 0 if ok otherwise errorcode
struct sensordev * sensor_register(struct sensordev *sensor)
register a new sensor. returns 0 if ok
Definition: sensor.c:644
const char * get_arg(const struct command *com, int index)
given an argument by index[0..n], will return a pointer to the bytearray (excluding the fieldtype) th...
int get_arg_size(const struct command *com, int index)
given an argument by index [0..n], will returns the size of the value in bytes. for a string/array it...
int(* mculib_serialport_write_char)(MCULIB_HANDLE handle, int portnum, uint8_t b)
write to serial port
Definition: user_app_info.h:51
int(* mculib_pin_in_callback)(MCULIB_HANDLE handle, pin_irq_callback pic)
set a callback to be called whenever a pin irq is triggered
Definition: user_app_info.h:71
void(* stop)()
last thing to be called. no more userloops or irqs afterwards
int(* mculib_pin_in)(MCULIB_HANDLE handle, int pinnum, int speed, int mode)
configure and enable an IO-Pin as input note: pinnum are sequential 0-99 are PAnn,...
Definition: user_app_info.h:67
int(* mculib_spi_write_only)(MCULIB_HANDLE handle, int portnum, const uint16_t write)
write a byte, discard the read if a transmission is already in progress wait until transmission is do...
int(* mculib_pin_release)(MCULIB_HANDLE handle, int pinnum)
deconfigure a pin (MCULIB_HANDLE handle,used for a different purpose)
Definition: user_app_info.h:79
int(* on_command_received)(struct command *com)
this is called for each command we receive
int(* hijack_usb_acm)(void(*receive_hook)(uint8_t *received, int size))
"hijack" the usb port. this means the firmware will neither send bytes through the port nor process i...
long(* mculib_get_seconds_since_boot)(void)
get number of seconds elapsed since boot or power-up this counter is usually ever-increasing and roug...
Definition: user_app_info.h:94
int(* hijack_esp32_usart)(void(*receive_hook)(uint8_t received))
hijack the esp32 serial port
int(* start)(int MCULIBHANDLE, struct sc_firmware_api *api)
guaranteed to be called by the firmware before any other functions
int(* mculib_spi_master_enable3)(MCULIB_HANDLE handle, int portnum, uint8_t wide, uint8_t clkpol, uint8_t cpha, uint8_t dir, uint32_t baud_in_khz)
enable a spi port as master and set clkpol, cpha and width (wide=0 8bit, wide=1 16bit)(dir == 0=RW,...
uint32_t(* userconfig_size)()
the userconfig: this is a little unstructured piece of flash set aside for configuration of userapps....
void(* printf)(const char *format,...)
print a message on console and possibly forward to server into logfile as well (uses radio - expensiv...
Definition: user_app_info.h:34
int(* mculib_serialport_enable)(MCULIB_HANDLE handle, int portnum, int baudrate)
configure a serial port with specified parameters num == 1..n (depending on mcu) baudrate == ....
Definition: user_app_info.h:42
int(* user_serialport_callback)(MCULIB_HANDLE handle, int portnum, serial_recv_callback cb)
set callback for serialport receive irq
Definition: user_app_info.h:47
int(* userconfig_copy)(uint8_t *buf, uint16_t bufsize, uint16_t *actual_size)
this copies the userconfig into a ram buffer, IF the version has been updated and IF the destination ...
int(* mculib_pin_set)(MCULIB_HANDLE handle, int pinnum, int highlow)
set IOPin to high or low
Definition: user_app_info.h:75
int(* mculib_spi_disable)(MCULIB_HANDLE handle, int portnum)
disable the spi port
Definition: user_app_info.h:98
int(* send_via_usb_acm)(uint8_t *buf, int size)
once a usb_acm is "hijacked", the userapp can send bytes through the usb_acm port with this function ...
int(* mculib_spi_write_and_read)(MCULIB_HANDLE handle, int portnum, const uint16_t write, uint16_t *read)
write a byte and read from spi if a transmission is already in progress it waits. this writes and wai...
int(* mculib_spi_read16_only)(MCULIB_HANDLE handle, int portnum, uint16_t *read)
there are weird devices, like tli4970, which aren't really spi. they basically start sending as soon ...
int(* mculib_pin_get)(MCULIB_HANDLE handle, int pinnum)
get current pin level (high or low) this is a bit funny: 0 or 1 indicate the pin level....
Definition: user_app_info.h:84
int(* userconfig_write)(uint8_t *buf, uint32_t size)
this saves a buf as "userconfig" RETURN VALUE: 0==ok, anything else is an error (same version is not ...
void(* on_new_node)(struct hostroute *host)
called when and if a new node is detected. this may be used, to, for example detect a route to the cl...
void(* user_loop)()
this is called frequently, but with no timing guarantees. essentially, it's called in the "idle-loop"...
void(* pin_pwm)(int MCULIBHANDLE, int pin, uint32_t newstate, int flags)
pwm a pin (mosfets, and some other pins as well)
void(* reset_userapp)(void)
reset the userapp
int(* mculib_serialport_write_string)(MCULIB_HANDLE handle, int port, const char *txt)
write a string to serial port
Definition: user_app_info.h:88
int(* mculib_pin_out)(MCULIB_HANDLE handle, int pinnum, int speed)
configure and enable an IO-Pin as output note: pinnum are sequential 0-99 are PAnn,...
Definition: user_app_info.h:56
int(* mcu_set_speed)(int MCULIBHANDLE, int speed)
change cpu speed - sometimes we need to be guaranteed to be fast. speed [1==very fast ....
int(* mculib_pin_out_opendrain)(MCULIB_HANDLE handle, int pinnum, int speed)
configure and enable an IO-Pin as output note: pinnum are sequential 0-99 are PAnn,...
Definition: user_app_info.h:61
int(* mculib_spi_speed)(MCULIB_HANDLE handle, int portnum, long khz)
set the spi speed (after it's open and running) returns new speed or 0 if failure
void(* proto_release)(void *buf)
release a proto struct
uint32_t(* userconfig_version)()
each time the config is updated, the version is incremented. in other words, unless the version is ch...
int com
Definition: command.h:22
long target
Definition: command.h:16
uint8_t encoding
Definition: command.h:11
int index
Definition: command.h:13
uint8_t flags
Definition: command.h:23
these are the callbacks available. the firmware "api". provided to the app on startup
Definition: user_app_info.h:29
this must be implemented by the userapp, stored in flash at the beginning of the file (offset 0)
user application interface