From 26934a09846e5abc1f6e75b454ab16d9d055418b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 7 Jan 2018 13:04:19 +0100 Subject: [PATCH] Implemented PINOUT.TXT file --- comm/messages.c | 14 +++++++-- comm/msg_bulkwrite.c | 6 ++-- framework/resources.c | 61 +++++++++++++++++++++++++++++++++++++-- framework/resources.h | 3 ++ framework/settings.c | 54 ++++++++++++++++++++-------------- framework/settings.h | 14 ++------- framework/unit_registry.c | 26 +++++++++++++++++ framework/unit_registry.h | 7 +++++ platform/pin_utils.c | 10 +++---- platform/platform.c | 28 ++++++++++++++++++ platform/platform.h | 4 +++ utils/error.h | 1 - utils/ini_writer.c | 7 +++++ utils/ini_writer.h | 8 +++++ vfs/vfs_user.c | 35 +++++++++++----------- 15 files changed, 216 insertions(+), 62 deletions(-) diff --git a/comm/messages.c b/comm/messages.c index 46e2ab7..dec78d6 100644 --- a/comm/messages.c +++ b/comm/messages.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; } diff --git a/comm/msg_bulkwrite.c b/comm/msg_bulkwrite.c index dbbfe7b..7dbafd4 100644 --- a/comm/msg_bulkwrite.c +++ b/comm/msg_bulkwrite.c @@ -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 = { diff --git a/framework/resources.c b/framework/resources.c index 5e19876..1c14cb3 100644 --- a/framework/resources.c +++ b/framework/resources.c @@ -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< +#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); } // --------------------------------------------------------------- diff --git a/framework/settings.h b/framework/settings.h index c256d7b..307129e 100644 --- a/framework/settings.h +++ b/framework/settings.h @@ -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 diff --git a/framework/unit_registry.c b/framework/unit_registry.c index 5b90279..27ef88e 100644 --- a/framework/unit_registry.c +++ b/framework/unit_registry.c @@ -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); +} diff --git a/framework/unit_registry.h b/framework/unit_registry.h index bb4ecbb..d42f76a 100644 --- a/framework/unit_registry.h +++ b/framework/unit_registry.h @@ -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 diff --git a/platform/pin_utils.c b/platform/pin_utils.c index 25c5feb..2278d8f 100644 --- a/platform/pin_utils.c +++ b/platform/pin_utils.c @@ -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); } diff --git a/platform/platform.c b/platform/platform.c index 56ca9a3..e2eff32 100644 --- a/platform/platform.c +++ b/platform/platform.c @@ -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); +} diff --git a/platform/platform.h b/platform/platform.h index e3e2a4b..a4bbe58 100644 --- a/platform/platform.h +++ b/platform/platform.h @@ -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 diff --git a/utils/error.h b/utils/error.h index 1b294a5..7c624be 100644 --- a/utils/error.h +++ b/utils/error.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) \ diff --git a/utils/ini_writer.c b/utils/ini_writer.c index a7c69f4..52440cb 100644 --- a/utils/ini_writer.c +++ b/utils/ini_writer.c @@ -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; +} diff --git a/utils/ini_writer.h b/utils/ini_writer.h index 908219e..7f77ae9 100644 --- a/utils/ini_writer.h +++ b/utils/ini_writer.h @@ -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 diff --git a/vfs/vfs_user.c b/vfs/vfs_user.c index 40e48bf..ea9410b 100644 --- a/vfs/vfs_user.c +++ b/vfs/vfs_user.c @@ -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