now it's possible to read and write SYSTEM.INI using bulk
This commit is contained in:
+42
-34
@@ -18,7 +18,7 @@ enum ComportSelection gActiveComport = COMPORT_USB; // start with USB so the han
|
|||||||
static uint32_t last_switch_time = 0; // started with USB
|
static uint32_t last_switch_time = 0; // started with USB
|
||||||
static bool xfer_verify_done = false;
|
static bool xfer_verify_done = false;
|
||||||
|
|
||||||
static void configure_interface(enum ComportSelection iface);
|
static bool configure_interface(enum ComportSelection iface);
|
||||||
|
|
||||||
/** Switch com transfer if the current one doesnt seem to work */
|
/** Switch com transfer if the current one doesnt seem to work */
|
||||||
void com_switch_transfer_if_needed(void)
|
void com_switch_transfer_if_needed(void)
|
||||||
@@ -30,8 +30,8 @@ void com_switch_transfer_if_needed(void)
|
|||||||
|
|
||||||
if (gActiveComport == COMPORT_USB) {
|
if (gActiveComport == COMPORT_USB) {
|
||||||
if (elapsed > 1000) {
|
if (elapsed > 1000) {
|
||||||
// USB may or may not work, depending on whether the module is plugged -
|
// USB may or may not work, depending on whether the module is plugged in
|
||||||
// in or running from a battery/external supply remotely.
|
// or running from a battery/external supply remotely.
|
||||||
|
|
||||||
// Check if USB is enumerated
|
// Check if USB is enumerated
|
||||||
|
|
||||||
@@ -39,19 +39,30 @@ void com_switch_transfer_if_needed(void)
|
|||||||
if (0 == uadr) {
|
if (0 == uadr) {
|
||||||
dbg("Not enumerated, assuming USB is dead");
|
dbg("Not enumerated, assuming USB is dead");
|
||||||
|
|
||||||
// Fallback to bare USART
|
// Fallback to radio or bare USART
|
||||||
|
do {
|
||||||
|
if (SystemSettings.use_comm_nordic) {
|
||||||
|
if (configure_interface(COMPORT_NORDIC)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SystemSettings.use_comm_lora) {
|
||||||
|
if (configure_interface(COMPORT_LORA)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (SystemSettings.use_comm_uart) {
|
if (SystemSettings.use_comm_uart) {
|
||||||
configure_interface(COMPORT_USART);
|
// after nordic/lora
|
||||||
|
if (configure_interface(COMPORT_USART)) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (SystemSettings.use_comm_nordic) {
|
|
||||||
configure_interface(COMPORT_NORDIC); // this fallbacks to LoRa if LoRa enabled
|
|
||||||
}
|
|
||||||
else if (SystemSettings.use_comm_lora) {
|
|
||||||
configure_interface(COMPORT_LORA);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dbg("No alternate com interface configured, leaving USB enabled.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbg("No alternate com interface configured.");
|
||||||
|
gActiveComport = COMPORT_NONE;
|
||||||
|
} while (0);
|
||||||
} else {
|
} else {
|
||||||
dbg("USB got address 0x%02x - OK", (int)uadr);
|
dbg("USB got address 0x%02x - OK", (int)uadr);
|
||||||
}
|
}
|
||||||
@@ -131,7 +142,7 @@ void com_iface_flush_buffer(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void configure_interface(enum ComportSelection iface)
|
static bool configure_interface(enum ComportSelection iface)
|
||||||
{
|
{
|
||||||
// Teardown
|
// Teardown
|
||||||
if (gActiveComport == COMPORT_USB) {
|
if (gActiveComport == COMPORT_USB) {
|
||||||
@@ -146,11 +157,17 @@ static void configure_interface(enum ComportSelection iface)
|
|||||||
__HAL_RCC_USART2_CLK_DISABLE();
|
__HAL_RCC_USART2_CLK_DISABLE();
|
||||||
irqd_detach(USART2, com_UsartIrqHandler);
|
irqd_detach(USART2, com_UsartIrqHandler);
|
||||||
}
|
}
|
||||||
gActiveComport = COMPORT_NONE;
|
else if (gActiveComport == COMPORT_NORDIC) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gActiveComport = iface;
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
if (iface == COMPORT_USB) {
|
if (iface == COMPORT_USB) {
|
||||||
trap("illegal"); // this never happens
|
trap("illegal"); // this never happens
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else if (iface == COMPORT_USART) {
|
else if (iface == COMPORT_USART) {
|
||||||
dbg("Setting up UART transfer");
|
dbg("Setting up UART transfer");
|
||||||
@@ -171,37 +188,28 @@ static void configure_interface(enum ComportSelection iface)
|
|||||||
LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX);
|
LL_USART_SetTransferDirection(USART2, LL_USART_DIRECTION_TX_RX);
|
||||||
|
|
||||||
LL_USART_Enable(USART2);
|
LL_USART_Enable(USART2);
|
||||||
|
|
||||||
|
return true; // always OK (TODO check voltage on Rx if it's 3V3 when idle?)
|
||||||
}
|
}
|
||||||
else {
|
else if (iface == COMPORT_NORDIC) {
|
||||||
if (iface == COMPORT_NORDIC) {
|
|
||||||
// Try to configure nordic
|
// Try to configure nordic
|
||||||
dbg("Setting up nRF transfer");
|
dbg("Setting up nRF transfer");
|
||||||
|
|
||||||
// TODO set up and check nRF transport
|
// TODO set up and check nRF transport
|
||||||
|
|
||||||
|
|
||||||
// On failure, try setting up LoRa
|
// On failure, try setting up LoRa
|
||||||
dbg("nRF failed to init");
|
dbg("nRF failed to init");
|
||||||
if (SystemSettings.use_comm_lora) {
|
return false;
|
||||||
iface = COMPORT_LORA;
|
|
||||||
} else {
|
|
||||||
iface = COMPORT_NONE; // fail
|
|
||||||
}
|
}
|
||||||
}
|
else if (iface == COMPORT_LORA) {
|
||||||
|
|
||||||
if (iface == COMPORT_LORA) {
|
|
||||||
// Try to configure nordic
|
// Try to configure nordic
|
||||||
dbg("Setting up LoRa transfer");
|
dbg("Setting up LoRa transfer");
|
||||||
|
|
||||||
// TODO set up and check LoRa transport
|
// TODO set up and check LoRa transport
|
||||||
|
|
||||||
dbg("LoRa failed to init");
|
dbg("LoRa failed to init");
|
||||||
iface = COMPORT_NONE; // fail
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trap("Bad iface %d", iface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iface == COMPORT_NONE) {
|
|
||||||
dbg("NO COM PORT AVAILABLE!");
|
|
||||||
}
|
|
||||||
|
|
||||||
gActiveComport = iface;
|
|
||||||
}
|
|
||||||
|
|||||||
+31
-12
@@ -58,26 +58,33 @@ static TF_Result lst_list_units(TinyFrame *tf, TF_Msg *msg)
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Callback for bulk read of the settings file */
|
/** Callback for bulk read of a settings file */
|
||||||
static void settings_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer)
|
static void ini_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer)
|
||||||
{
|
{
|
||||||
// clean-up request
|
// clean-up request
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
free_ck(bulk);
|
free_ck(bulk);
|
||||||
iw_end();
|
iw_end();
|
||||||
// dbg("INI read complete.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bulk->offset == 0) iw_begin();
|
if (bulk->offset == 0) iw_begin();
|
||||||
|
|
||||||
IniWriter iw = iw_init((char *)buffer, bulk->offset, chunk);
|
IniWriter iw = iw_init((char *)buffer, bulk->offset, chunk);
|
||||||
iw.tag = 1;
|
iw.tag = 1; // indicates this is read via the API (affects some comments)
|
||||||
|
|
||||||
|
uint8_t filenum = (uint8_t) (int) bulk->userdata;
|
||||||
|
|
||||||
|
if (filenum == 0) {
|
||||||
settings_build_units_ini(&iw);
|
settings_build_units_ini(&iw);
|
||||||
}
|
}
|
||||||
|
else if (filenum == 1) {
|
||||||
|
settings_build_system_ini(&iw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener: Export INI file via TF
|
* Listener: Export a file via TF
|
||||||
*/
|
*/
|
||||||
static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
|
static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
|
||||||
{
|
{
|
||||||
@@ -86,14 +93,29 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
|
|||||||
BulkRead *bulk = malloc_ck(sizeof(BulkRead));
|
BulkRead *bulk = malloc_ck(sizeof(BulkRead));
|
||||||
assert_param(bulk != NULL);
|
assert_param(bulk != NULL);
|
||||||
|
|
||||||
|
uint8_t filenum = 0;
|
||||||
|
|
||||||
|
// if any payload, the first byte defines the file to read
|
||||||
|
// 0 - units
|
||||||
|
// 1 - system
|
||||||
|
// (this is optional for backwards compatibility)
|
||||||
|
if (msg->len > 0) {
|
||||||
|
filenum = msg->data[0];
|
||||||
|
}
|
||||||
|
|
||||||
bulk->frame_id = msg->frame_id;
|
bulk->frame_id = msg->frame_id;
|
||||||
|
bulk->read = ini_bulkread_cb;
|
||||||
|
bulk->userdata = (void *) (int)filenum;
|
||||||
|
|
||||||
|
if (filenum == 0) {
|
||||||
bulk->len = iw_measure_total(settings_build_units_ini, 1);
|
bulk->len = iw_measure_total(settings_build_units_ini, 1);
|
||||||
bulk->read = settings_bulkread_cb;
|
}
|
||||||
bulk->userdata = NULL;
|
else if (filenum == 1) {
|
||||||
|
bulk->len = iw_measure_total(settings_build_system_ini, 1);
|
||||||
|
}
|
||||||
|
|
||||||
bulkread_start(tf, bulk);
|
bulkread_start(tf, bulk);
|
||||||
Indicator_Effect(STATUS_DISK_BUSY_SHORT);
|
Indicator_Effect(STATUS_DISK_BUSY_SHORT);
|
||||||
|
|
||||||
return TF_STAY;
|
return TF_STAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +164,7 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
|
|||||||
PayloadParser pp = pp_start(msg->data, msg->len, NULL);
|
PayloadParser pp = pp_start(msg->data, msg->len, NULL);
|
||||||
uint32_t len = pp_u32(&pp);
|
uint32_t len = pp_u32(&pp);
|
||||||
if (!pp.ok) {
|
if (!pp.ok) {
|
||||||
com_respond_error(msg->frame_id, E_PROTOCOL_BREACH);
|
com_respond_error(msg->frame_id, E_MALFORMED_COMMAND);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,11 +173,8 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
|
|||||||
|
|
||||||
settings_load_ini_begin();
|
settings_load_ini_begin();
|
||||||
ini_parse_begin(iniparser_cb, NULL);
|
ini_parse_begin(iniparser_cb, NULL);
|
||||||
|
|
||||||
bulkwrite_start(tf, bulk);
|
bulkwrite_start(tf, bulk);
|
||||||
|
|
||||||
Indicator_Effect(STATUS_DISK_BUSY);
|
Indicator_Effect(STATUS_DISK_BUSY);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return TF_STAY;
|
return TF_STAY;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
// Created by MightyPork on 2017/12/02.
|
// Created by MightyPork on 2017/12/02.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <platform/debug_uart.h>
|
|
||||||
#include <comm/interfaces.h>
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "system_settings.h"
|
#include "system_settings.h"
|
||||||
#include "utils/str_utils.h"
|
#include "utils/str_utils.h"
|
||||||
@@ -11,6 +9,8 @@
|
|||||||
#include "cfg_utils.h"
|
#include "cfg_utils.h"
|
||||||
#include "resources.h"
|
#include "resources.h"
|
||||||
#include "unit_base.h"
|
#include "unit_base.h"
|
||||||
|
#include "platform/debug_uart.h"
|
||||||
|
#include "comm/interfaces.h"
|
||||||
|
|
||||||
static void systemsettings_mco_teardown(void);
|
static void systemsettings_mco_teardown(void);
|
||||||
static void systemsettings_mco_init(void);
|
static void systemsettings_mco_init(void);
|
||||||
@@ -171,18 +171,34 @@ void systemsettings_build_ini(IniWriter *iw)
|
|||||||
iw_entry_d(iw, "mco-prediv", (1<<SystemSettings.mco_prediv));
|
iw_entry_d(iw, "mco-prediv", (1<<SystemSettings.mco_prediv));
|
||||||
|
|
||||||
iw_cmt_newline(iw);
|
iw_cmt_newline(iw);
|
||||||
iw_comment(iw, "Allowed fallback communication ports");
|
iw_comment(iw, "--- Allowed fallback communication ports ---");
|
||||||
|
|
||||||
iw_comment(iw, "UART Tx:PA2, Rx:PA2");
|
iw_cmt_newline(iw);
|
||||||
|
iw_comment(iw, "UART Tx:PA2, Rx:PA3");
|
||||||
iw_entry_s(iw, "com-uart", str_yn(SystemSettings.use_comm_uart));
|
iw_entry_s(iw, "com-uart", str_yn(SystemSettings.use_comm_uart));
|
||||||
iw_entry_d(iw, "com-uart-baud", SystemSettings.comm_uart_baud);
|
iw_entry_d(iw, "com-uart-baud", SystemSettings.comm_uart_baud);
|
||||||
|
|
||||||
|
iw_cmt_newline(iw);
|
||||||
|
iw_comment(iw, "nRF24L01+ radio");
|
||||||
|
iw_entry_s(iw, "com-nrf", str_yn(SystemSettings.use_comm_nordic));
|
||||||
|
|
||||||
|
iw_comment(iw, "nRF channel");
|
||||||
|
iw_entry_d(iw, "nrf-channel", SystemSettings.nrf_channel);
|
||||||
|
|
||||||
|
iw_comment(iw, "nRF network ID (hex, 4 bytes, little-endian)");
|
||||||
|
iw_entry(iw, "nrf-network", "%02X.%02X.%02X.%02X",
|
||||||
|
SystemSettings.nrf_network[0],
|
||||||
|
SystemSettings.nrf_network[1],
|
||||||
|
SystemSettings.nrf_network[2],
|
||||||
|
SystemSettings.nrf_network[3]);
|
||||||
|
|
||||||
|
iw_comment(iw, "nRF node address (hex, 1 byte, > 0)");
|
||||||
|
iw_entry(iw, "nrf-address", "%02X",
|
||||||
|
SystemSettings.nrf_address);
|
||||||
|
|
||||||
// those aren't implement yet, don't tease the user
|
// those aren't implement yet, don't tease the user
|
||||||
// TODO show pin-out, extra settings if applicable
|
// TODO show pin-out, extra settings if applicable
|
||||||
#if 0
|
#if 0
|
||||||
iw_comment(iw, "nRF24L01+");
|
|
||||||
iw_entry_s(iw, "com-nordic", str_yn(SystemSettings.use_comm_nrf24l01p));
|
|
||||||
|
|
||||||
iw_comment(iw, "LoRa/GFSK sx127x");
|
iw_comment(iw, "LoRa/GFSK sx127x");
|
||||||
iw_entry_s(iw, "com-lora", str_yn(SystemSettings.use_comm_sx127x));
|
iw_entry_s(iw, "com-lora", str_yn(SystemSettings.use_comm_sx127x));
|
||||||
#endif
|
#endif
|
||||||
@@ -241,12 +257,24 @@ bool systemsettings_load_ini(const char *restrict key, const char *restrict valu
|
|||||||
if (suc) SystemSettings.comm_uart_baud = baud;
|
if (suc) SystemSettings.comm_uart_baud = baud;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
if (streq(key, "com-nrf")) {
|
||||||
if (streq(key, "com-nordic")) {
|
|
||||||
bool yn = cfg_bool_parse(value, &suc);
|
bool yn = cfg_bool_parse(value, &suc);
|
||||||
if (suc) SystemSettings.use_comm_nordic = yn;
|
if (suc) SystemSettings.use_comm_nordic = yn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (streq(key, "nrf-channel")) {
|
||||||
|
SystemSettings.nrf_channel = cfg_u8_parse(value, &suc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(key, "nrf-address")) {
|
||||||
|
cfg_hex_parse(&SystemSettings.nrf_address, 1, value, &suc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq(key, "nrf-network")) {
|
||||||
|
cfg_hex_parse(&SystemSettings.nrf_network[0], 4, value, &suc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (streq(key, "com-lora")) {
|
if (streq(key, "com-lora")) {
|
||||||
bool yn = cfg_bool_parse(value, &suc);
|
bool yn = cfg_bool_parse(value, &suc);
|
||||||
if (suc) SystemSettings.use_comm_lora = yn;
|
if (suc) SystemSettings.use_comm_lora = yn;
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ struct system_settings {
|
|||||||
uint32_t comm_uart_baud; // baud rate for the uart transport
|
uint32_t comm_uart_baud; // baud rate for the uart transport
|
||||||
bool use_comm_lora; // SX1276/8
|
bool use_comm_lora; // SX1276/8
|
||||||
bool use_comm_nordic; // nRF24L01+
|
bool use_comm_nordic; // nRF24L01+
|
||||||
|
uint8_t nrf_channel;
|
||||||
|
uint8_t nrf_network[4];
|
||||||
|
uint8_t nrf_address;
|
||||||
|
|
||||||
// Support flags put here for scoping, but not atcually part of the persistent settings
|
// Support flags put here for scoping, but not atcually part of the persistent settings
|
||||||
volatile bool editable; //!< True if we booted with the LOCK jumper removed
|
volatile bool editable; //!< True if we booted with the LOCK jumper removed
|
||||||
|
|||||||
@@ -297,3 +297,46 @@ uint32_t cfg_enum4_parse(const char *value,
|
|||||||
*suc = false;
|
*suc = false;
|
||||||
return na;
|
return na;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cfg_hex_parse(uint8_t *dest, uint32_t count, const char *value, bool *suc)
|
||||||
|
{
|
||||||
|
// discard possible leading 0x
|
||||||
|
if (value[0] == '0' && value[1] == 'x') {
|
||||||
|
value += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t bytebuf = 0;
|
||||||
|
for (uint32_t digit = 0; digit < count * 2;) {
|
||||||
|
char v = *value;
|
||||||
|
if (v != 0) value++;
|
||||||
|
|
||||||
|
uint8_t nibble = 0;
|
||||||
|
if (v == ' ' || v == '.' || v == '-' || v == ':') {
|
||||||
|
continue; // junk
|
||||||
|
}
|
||||||
|
else if (v >= '0' && v <= '9') {
|
||||||
|
nibble = (uint8_t) (v - '0');
|
||||||
|
}
|
||||||
|
else if (v >= 'a' && v <= 'f') {
|
||||||
|
nibble = (uint8_t) (10 + (v - 'a'));
|
||||||
|
}
|
||||||
|
else if (v >= 'A' && v <= 'F') {
|
||||||
|
nibble = (uint8_t) (10 + (v - 'A'));
|
||||||
|
}
|
||||||
|
else if (v == 0) {
|
||||||
|
nibble = 0; // pad with zeros
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*suc = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit++;
|
||||||
|
bytebuf <<= 4;
|
||||||
|
bytebuf |= nibble;
|
||||||
|
if ((digit % 2 == 0) && digit > 0) { // whole byte
|
||||||
|
*dest++ = bytebuf;
|
||||||
|
bytebuf = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -116,6 +116,18 @@ uint32_t cfg_enum4_parse(const char *tpl,
|
|||||||
const char *d, uint32_t nd,
|
const char *d, uint32_t nd,
|
||||||
bool *suc);
|
bool *suc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a hexa string to a byte array.
|
||||||
|
* Skips 0x prefix, '.', '-', ':', ' '.
|
||||||
|
*
|
||||||
|
* @param[out] dest - storage array
|
||||||
|
* @param[in] count - expected number of bytes
|
||||||
|
* @param[in] value - parsed string
|
||||||
|
* @param[out] suc - success flag
|
||||||
|
*/
|
||||||
|
void cfg_hex_parse(uint8_t *dest, uint32_t count,
|
||||||
|
const char *value, bool *suc);
|
||||||
|
|
||||||
/** Convert bool to a Y or N constant string */
|
/** Convert bool to a Y or N constant string */
|
||||||
#define str_yn(cond) ((cond) ? ("Y") : ("N"))
|
#define str_yn(cond) ((cond) ? ("Y") : ("N"))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user