Implemented PINOUT.TXT file

sipo
Ondřej Hruška 6 years ago
parent ad39fc280f
commit 26934a0984
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 14
      comm/messages.c
  2. 6
      comm/msg_bulkwrite.c
  3. 61
      framework/resources.c
  4. 3
      framework/resources.h
  5. 54
      framework/settings.c
  6. 14
      framework/settings.h
  7. 26
      framework/unit_registry.c
  8. 7
      framework/unit_registry.h
  9. 10
      platform/pin_utils.c
  10. 28
      platform/platform.c
  11. 4
      platform/platform.h
  12. 1
      utils/error.h
  13. 7
      utils/ini_writer.c
  14. 8
      utils/ini_writer.h
  15. 35
      vfs/vfs_user.c

@ -80,7 +80,7 @@ static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
assert_param(bulk);
bulk->frame_id = msg->frame_id;
bulk->len = settings_get_units_ini_len();
bulk->len = iw_measure_total(settings_build_units_ini);
bulk->read = settings_bulkread_cb;
bulk->userdata = NULL;
@ -124,7 +124,16 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
assert_param(bulk);
bulk->frame_id = msg->frame_id;
bulk->len = settings_get_units_ini_len();
// we get the total len in the payload - ini can be as long as it wants, we parse it on-line
PayloadParser pp = pp_start(msg->data, msg->len, NULL);
uint32_t len = pp_u32(&pp);
if (!pp.ok) {
com_respond_error(msg->frame_id, E_PROTOCOL_BREACH);
goto done;
}
bulk->len = len;
bulk->write = settings_bulkwrite_cb;
settings_load_ini_begin();
@ -132,6 +141,7 @@ static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
bulkwrite_start(tf, bulk);
done:
return TF_STAY;
}

@ -30,7 +30,7 @@ static TF_Result bulkwrite_lst(TinyFrame *tf, TF_Msg *msg)
else if (msg->type == MSG_BULK_DATA || msg->type == MSG_BULK_END) {
// if past len, speak up
if (bulk->offset >= bulk->len) {
com_respond_error(bulk->frame_id, E_OVERRUN);
com_respond_error(bulk->frame_id, E_PROTOCOL_BREACH);
goto close;
}
@ -71,8 +71,8 @@ void bulkwrite_start(TinyFrame *tf, BulkWrite *bulk)
{
uint8_t buf[8];
PayloadBuilder pb = pb_start(buf, 8, NULL);
pb_u32(&pb, bulk->len);
pb_u32(&pb, TF_MAX_PAYLOAD_RX);
pb_u32(&pb, bulk->len); // total expected len
pb_u32(&pb, TF_MAX_PAYLOAD_RX); // max chunk size
// We use userdata1 to hold a reference to the bulk transfer
TF_Msg msg = {

@ -26,12 +26,12 @@ const char * rsc_get_name(Resource rsc)
{
assert_param(rsc < RESOURCE_COUNT);
static char gpionamebuf[4];
static char gpionamebuf[5];
if (rsc >= R_PA0) {
// we assume the returned value is not stored anywhere
// and is directly used in a sprintf call.
uint8_t index = rsc - R_PA0;
SNPRINTF(gpionamebuf, 4, "%c%d", 'A'+(index/16), index%16);
SNPRINTF(gpionamebuf, 5, "P%c%d", 'A'+(index/16), index%16);
return gpionamebuf;
}
@ -219,3 +219,60 @@ void rsc_teardown(Unit *unit)
unit->resources[i] = 0;
}
}
void rsc_print_all_available(IniWriter *iw)
{
if (iw->count == 0) return;
static char buf[80];
iw_string(iw, "Resources available on this platform\r\n"
"------------------------------------\r\n");
ResourceMap scratchmap = {};
for (uint32_t i = 0; i < RSCMAP_LEN; i++) {
scratchmap[i] = UNIT_PLATFORM.resources[i] | UNIT_SYSTEM.resources[i];
}
uint32_t count0 = (iw->count + iw->skip);
bool first = true;
for (uint32_t rsc = 0; rsc < R_PA0; rsc++) {
if (RSC_IS_HELD(scratchmap, (Resource)rsc)) continue;
if (!first) iw_string(iw, ", ");
// automatic newlines
if (count0 - (iw->count + iw->skip) >= 55) {
iw_newline(iw);
count0 = (iw->count + iw->skip);
}
iw_string(iw, rsc_get_name((Resource) rsc));
first = false;
}
// GPIOs will be printed using the range format
uint16_t bitmap = 0;
for (uint32_t rsc = R_PA0, i = 0; rsc <= R_PF15; rsc++, i++) {
if (i%16 == 0) {
// here we print the previous port
if (bitmap != 0) {
iw_string(iw, str_pinmask(bitmap, buf));
bitmap = 0;
}
// first of a port
iw_newline(iw);
iw_sprintf(iw, "P%c: ", (char)('A' + (i/16)));
}
if (RSC_IS_FREE(scratchmap, (Resource)rsc)) {
bitmap |= 1<<i%16;
}
}
// the last one
if (bitmap != 0) {
iw_string(iw, str_pinmask(bitmap, buf));
}
iw_newline(iw);
iw_newline(iw);
}

@ -36,4 +36,7 @@ const char * rsc_get_name(Resource rsc);
/** Get rsc owner name */
const char * rsc_get_owner_name(Resource rsc);
/** Print all available resource names */
void rsc_print_all_available(IniWriter *iw);
#endif //GEX_RESOURCES_H

@ -2,13 +2,14 @@
// Created by MightyPork on 2017/11/26.
//
#include <utils/avrlibc.h>
#include "utils/avrlibc.h"
#include "platform.h"
#include "utils/hexdump.h"
#include "settings.h"
#include "unit_registry.h"
#include "system_settings.h"
#include "utils/str_utils.h"
#include "unit_base.h"
// pre-declarations
static void savebuf_flush(PayloadBuilder *pb, bool final);
@ -211,27 +212,37 @@ static void savebuf_flush(PayloadBuilder *pb, bool final)
// ---------------------------------------------------------------
static void ini_preamble(IniWriter *iw, const char *filename)
static void gex_file_preamble(IniWriter *iw, const char *filename)
{
// File header
// File header
iw_hdr_comment(iw, filename);
iw_hdr_comment(iw, "GEX v%s on %s", GEX_VERSION, GEX_PLATFORM);
iw_hdr_comment(iw, "built %s at %s", __DATE__, __TIME__);
iw_cmt_newline(iw);
}
static void ini_preamble(IniWriter *iw, const char *filename)
{
gex_file_preamble(iw, filename);
iw_comment(iw, "Overwrite this file to change settings.");
iw_comment(iw, "Close the LOCK jumper to save them to Flash.");
#if PLAT_LOCK_BTN
iw_comment(iw, "Press the LOCK button to save them to Flash.");
#else
iw_comment(iw, "Close the LOCK jumper to save them to Flash.");
#endif
}
// --- UNITS.INI ---
extern osMutexId mutScratchBufferHandle;
/**
* Write system settings to INI (without section)
* Build units ini file
*/
void settings_build_units_ini(IniWriter *iw)
{
ini_preamble(iw, "UNITS.INI");
assert_param(osOK == osMutexWait(mutScratchBufferHandle, 5000));
{
ureg_build_ini(iw);
@ -239,31 +250,32 @@ void settings_build_units_ini(IniWriter *iw)
assert_param(osOK == osMutexRelease(mutScratchBufferHandle));
}
// --- SYSTEM.INI ---
/**
* Write system settings to INI (without section)
* Build system settings ini file
*/
void settings_build_system_ini(IniWriter *iw)
{
ini_preamble(iw, "SYSTEM.INI");
systemsettings_build_ini(iw);
}
uint32_t settings_get_units_ini_len(void)
{
// this writer is configured to skip everything, so each written byte will decrement the skip count
IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1); // count is never used, we use 1 because 0 means we're full
settings_build_units_ini(&iw);
// now we just check how many bytes were skipped
return 0xFFFFFFFF - iw.skip;
}
// --- PINOUT.TXT ---
/** print system pin.-out info (platform.c) */
extern void plat_print_system_pinout(IniWriter *iw);
uint32_t settings_get_system_ini_len(void)
/**
* Build pinout info file
*/
void settings_build_pinout_txt(IniWriter *iw)
{
// same as above
IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1);
settings_build_system_ini(&iw);
return 0xFFFFFFFF - iw.skip;
gex_file_preamble(iw, "PINOUT.TXT");
rsc_print_all_available(iw);
ureg_print_unit_resources(iw);
plat_print_system_pinout(iw);
}
// ---------------------------------------------------------------

@ -56,13 +56,6 @@ void settings_load_ini_end(void);
*/
void settings_build_units_ini(IniWriter *iw);
/**
* Get UNITS.INI len (expensive, uses dummy read)
*
* @return bytes
*/
uint32_t settings_get_units_ini_len(void);
/**
* Write SYSTEM.INI to iniwriter
* @param iw - writer handle
@ -70,10 +63,9 @@ uint32_t settings_get_units_ini_len(void);
void settings_build_system_ini(IniWriter *iw);
/**
* Get SYSTEM.INI len (expensive, uses dummy read)
*
* @return bytes
* Write UNITS.TXT to iniwriter
* @param iw - writer handle
*/
uint32_t settings_get_system_ini_len(void);
void settings_build_pinout_txt(IniWriter *iw);
#endif //GEX_SETTINGS_H

@ -557,3 +557,29 @@ Unit *ureg_get_rsc_owner(Resource resource)
return NULL;
}
void ureg_print_unit_resources(IniWriter *iw)
{
if (iw->count == 0) return;
iw_string(iw, "Resources held by units\r\n"
"-----------------------\r\n");
UlistEntry *li = ulist_head;
while (li != NULL) {
iw_string(iw, li->unit.name);
iw_string(iw, ": ");
bool first = true;
for (uint32_t rsc = 0; rsc < RESOURCE_COUNT; rsc++) {
if (!RSC_IS_HELD(li->unit.resources, (Resource)rsc)) continue;
if (!first) iw_string(iw, ", ");
iw_string(iw, rsc_get_name((Resource) rsc));
first = false;
}
if (first) iw_string(iw, "-none-");
iw_newline(iw);
li = li->next;
}
iw_newline(iw);
}

@ -135,4 +135,11 @@ void ureg_report_active_units(TF_ID frame_id);
*/
Unit *ureg_get_rsc_owner(Resource resource);
/**
* Print a overview of resources held by units
*
* @param iw
*/
void ureg_print_unit_resources(IniWriter *iw);
#endif //GEX_UNIT_REGISTRY_H

@ -208,15 +208,15 @@ char * str_pinmask(uint16_t pins, char *buffer)
} else {
if (on) {
if (!first) {
b += SPRINTF(b, ",");
b += SPRINTF(b, ", ");
}
if (start == (uint32_t)(i+1)) {
b += SPRINTF(b, "%"PRIu32, start);
}
else if (start == (uint32_t)(i+2)) {
// exception for 2-long ranges - don't show as range
b += SPRINTF(b, "%"PRIu32",%"PRIu32, start, i + 1);
}
// else if (start == (uint32_t)(i+2)) {
// // exception for 2-long ranges - don't show as range
// b += SPRINTF(b, "%"PRIu32",%"PRIu32, start, i + 1);
// }
else {
b += SPRINTF(b, "%"PRIu32"-%"PRIu32, start, i + 1);
}

@ -252,3 +252,31 @@ void plat_usb_reconnect(void)
}
void plat_print_system_pinout(IniWriter *iw)
{
if (iw->count == 0) return;
iw_string(iw, "System pin-out\r\n"
"--------------\r\n");
#if PLAT_LOCK_BTN
iw_sprintf(iw, "Lock button (active="
#if PLAT_LOCK_1CLOSED
"high"
#else
"low"
#endif
"): P%c%d\r\n", LOCK_JUMPER_PORT, LOCK_JUMPER_PIN);
#else
iw_sprintf(iw, "Lock jumper (closed="
#if PLAT_LOCK_1CLOSED
"high"
#else
"low"
#endif
"): P%c%d\r\n", LOCK_JUMPER_PORT, LOCK_JUMPER_PIN);
#endif
iw_sprintf(iw, "Indicator LED (anode): P%c%d\r\n", STATUS_LED_PORT, STATUS_LED_PIN);
iw_sprintf(iw, "System clock speed: %d MHz\r\n", PLAT_AHB_MHZ);
}

@ -33,6 +33,7 @@
// GEX version string
#include "version.h"
// ---
/**
@ -56,4 +57,7 @@ void plat_register_units(void);
*/
void plat_usb_reconnect(void);
// provided as extern
//void plat_print_system_pinout(IniWriter *iw);
#endif //GEX_PLATFORM_H

@ -39,7 +39,6 @@
X(NOT_APPLICABLE, NULL) \
X(HW_TIMEOUT, NULL) \
X(NO_SUCH_UNIT, NULL) \
X(OVERRUN, NULL) /* used in bulk transfer */ \
X(PROTOCOL_BREACH, NULL) /* eating with the wrong spoon */ \
X(BAD_UNIT_TYPE, NULL) \
X(NOT_IMPLEMENTED, NULL) \

@ -91,3 +91,10 @@ void iw_entry(IniWriter *iw, const char *key, const char *format, ...)
IW_VPRINTF();
iw_newline(iw); // one newline after entry
}
uint32_t iw_measure_total(void (*handler)(IniWriter *))
{
IniWriter iw = iw_init(NULL, 0xFFFFFFFF, 1);
handler(&iw);
return 0xFFFFFFFF - iw.skip;
}

@ -97,4 +97,12 @@ __attribute__((format(printf,2,3)));
void iw_entry(IniWriter *iw, const char *key, const char *format, ...)
__attribute__((format(printf,3,4)));
/**
* Measure total ini writer length using a dummy write
*
* @param handler - function that normally writes to the writer
* @return byte count
*/
uint32_t iw_measure_total(void (*handler)(IniWriter *));
#endif //INIWRITER_H

@ -27,33 +27,33 @@
const vfs_filename_t daplink_drive_name = VFS_DRIVE_NAME;
// File callback to be used with vfs_add_file to return file contents
static uint32_t read_file_units_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
static uint32_t read_iw_sector(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors, void (*handler)(IniWriter *))
{
vfs_printf("Read UNITS.INI");
const uint32_t avail = num_sectors*VFS_SECTOR_SIZE;
const uint32_t skip = sector_offset*VFS_SECTOR_SIZE;
IniWriter iw = iw_init((char *)data, skip, avail);
settings_build_units_ini(&iw);
handler(&iw);
return avail - iw.count;
}
// File callback to be used with vfs_add_file to return file contents
static uint32_t read_file_units_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
{
vfs_printf("Read UNITS.INI");
return read_iw_sector(sector_offset, data, num_sectors, settings_build_units_ini);
}
static uint32_t read_file_system_ini(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
{
vfs_printf("Read SYSTEM.INI");
const uint32_t avail = num_sectors*VFS_SECTOR_SIZE;
const uint32_t skip = sector_offset*VFS_SECTOR_SIZE;
IniWriter iw = iw_init((char *)data, skip, avail);
settings_build_system_ini(&iw);
return avail - iw.count;
return read_iw_sector(sector_offset, data, num_sectors, settings_build_system_ini);
}
static uint32_t read_file_pinout_txt(uint32_t sector_offset, uint8_t *data, uint32_t num_sectors)
{
vfs_printf("Read PINOUT.TXT");
return read_iw_sector(sector_offset, data, num_sectors, settings_build_pinout_txt);
}
void vfs_user_build_filesystem(void)
{
@ -62,8 +62,9 @@ void vfs_user_build_filesystem(void)
// Setup the filesystem based on target parameters
vfs_init(daplink_drive_name, 0/*unused "disk size"*/);
vfs_create_file("UNITS INI", read_file_units_ini, NULL, settings_get_units_ini_len());
vfs_create_file("SYSTEM INI", read_file_system_ini, NULL, settings_get_system_ini_len());
vfs_create_file("UNITS INI", read_file_units_ini, NULL, iw_measure_total(settings_build_units_ini));
vfs_create_file("SYSTEM INI", read_file_system_ini, NULL, iw_measure_total(settings_build_system_ini));
vfs_create_file("PINOUT TXT", read_file_pinout_txt, NULL, iw_measure_total(settings_build_pinout_txt));
}
// Callback to handle changes to the root directory. Should be used with vfs_set_file_change_callback

Loading…
Cancel
Save