I would like to see a progress callback. I have a crude patch that allows you
to set a progress callback function for programming flash devices. I found
this useful when programming devices from python. Is there any interest in
this? I can try to clean it up a bit and submit a patch.
On Jul 13, 2011, at 7:20 PM, Mike Frysinger wrote:
> loops that need to show progress bars now can do:
> urj_log_progress_init("foo");
> for (...) {
> urj_log_progress_tick(0);
> }
> urj_log_progress_done(URJ_STATUS_OK);
>
> not quite done yet, but the basic idea is here
> -mike
>
> --- include/urjtag/log.h (revision 1968)
> +++ include/urjtag/log.h (working copy)
> @@ -27,6 +27,14 @@
>
> #include "types.h"
>
> +typedef enum URJ_LOG_PROGRESS
> +{
> + URJ_LOG_PROGRESS_INIT,
> + URJ_LOG_PROGRESS_TICK,
> + URJ_LOG_PROGRESS_DONE,
> +}
> +urj_log_progress_t;
> +
> /**
> * Log state.
> */
> @@ -35,6 +43,7 @@ typedef struct URJ_LOG_STATE
> urj_log_level_t level; /**< logging level */
> int (*out_vprintf) (const char *fmt, va_list ap);
> int (*err_vprintf) (const char *fmt, va_list ap);
> + int (*progress) (urj_log_progress_t cmd, ...);
> }
> urj_log_state_t;
>
> @@ -85,4 +94,19 @@ urj_log_level_t urj_string_log_level (co
> */
> const char *urj_log_level_string (urj_log_level_t level);
>
> +/**
> + */
> +#define urj_log_progress_init(msg) \
> + urj_log_state.progress (URJ_LOG_PROGRESS_INIT, 0, msg)
> +#define urj_log_progress_init_spinner(msg) \
> + urj_log_state.progress (URJ_LOG_PROGRESS_INIT, 1, msg)
> +#define urj_log_progress_init_range(msg, start, end) \
> + urj_log_state.progress (URJ_LOG_PROGRESS_INIT, 2, msg, start, end)
> +
> +#define urj_log_progress_tick(pos) \
> + urj_log_state.progress (URJ_LOG_PROGRESS_TICK, pos)
> +
> +#define urj_log_progress_done(status) \
> + urj_log_state.progress (URJ_LOG_PROGRESS_DONE, status)
> +
> #endif /* URJ_LOG_H */
> --- src/bus/readmem.c (revision 1968)
> +++ src/bus/readmem.c (working copy)
> @@ -91,11 +91,11 @@ urj_bus_readmem (urj_bus_t *bus, FILE *f
>
> a = addr;
> end = a + len;
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("reading:\n"));
>
> if (URJ_BUS_READ_START (bus, addr) != URJ_STATUS_OK)
> return URJ_STATUS_FAIL;
>
> + urj_log_progress_init_range (_("reading"), addr, end);
> for (a += step; a <= end; a += step)
> {
> uint32_t data;
> @@ -117,20 +117,16 @@ urj_bus_readmem (urj_bus_t *bus, FILE *f
>
> if ((bc >= BSIZE) || (a >= end))
> {
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08llX\r"),
> - (long long unsigned) a);
> + urj_log_progress_tick (a);
> if (fwrite (b, bc, 1, f) != 1)
> {
> urj_error_set (URJ_ERROR_FILEIO, "fwrite fails");
> urj_error_state.sys_errno = ferror(f);
> clearerr(f);
> - return URJ_STATUS_FAIL;
> + return urj_log_progress_done (URJ_STATUS_FAIL);
> }
> bc = 0;
> }
> }
> -
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("\nDone.\n"));
> -
> - return URJ_STATUS_OK;
> + return urj_log_progress_done (URJ_STATUS_OK);
> }
> --- src/bus/writemem.c (revision 1968)
> +++ src/bus/writemem.c (working copy)
> @@ -85,8 +85,8 @@ urj_bus_writemem (urj_bus_t *bus, FILE *
>
> a = addr;
> end = a + len;
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("writing:\n"));
>
> + urj_log_progress_init_range (_("writing"), addr, end);
> for (; a < end; a += step)
> {
> uint32_t data;
> @@ -95,8 +95,7 @@ urj_bus_writemem (urj_bus_t *bus, FILE *
> /* Read one block of data */
> if (bc == 0)
> {
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08llX\r"),
> - (long long unsigned) a);
> + urj_log_progress_tick (a);
> bc = fread (b, 1, BSIZE, f);
> if (bc != BSIZE)
> {
> @@ -116,7 +115,7 @@ urj_bus_writemem (urj_bus_t *bus, FILE *
> clearerr(f);
> }
>
> - return URJ_STATUS_FAIL;
> + return urj_log_progress_done (URJ_STATUS_FAIL);
> }
> /* else, process what we have read, then return to fread() to
> * meet the error condition (again) */
> @@ -142,7 +141,5 @@ urj_bus_writemem (urj_bus_t *bus, FILE *
> URJ_BUS_WRITE (bus, a, data);
> }
>
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("\nDone.\n"));
> -
> - return URJ_STATUS_OK;
> + return urj_log_progress_done (URJ_STATUS_OK);
> }
> --- src/flash/flash.c (revision 1968)
> +++ src/flash/flash.c (working copy)
> @@ -39,6 +39,7 @@
> #include <stdlib.h>
> #include <string.h>
> #include <errno.h>
> +#include <sys/stat.h>
>
> #include <urjtag/error.h>
> #include <urjtag/log.h>
> @@ -308,6 +309,13 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> uint32_t write_buffer[BSIZE];
> int write_buffer_count;
> uint32_t write_buffer_adr;
> + struct stat st;
> +
> + if (fstat (fileno (f), &st))
> + {
> + urj_error_set (URJ_ERROR_NOTFOUND, _("no file found"));
> + return URJ_STATUS_FAIL;
> + }
>
> set_flash_driver ();
> if (!urj_flash_cfi_array || !flash_driver)
> @@ -335,7 +343,7 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> for (i = 0; i < neb; i++)
> erased[i] = 0;
>
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("program:\n"));
> + urj_log_progress_init_range (_("program"), addr, addr + st.st_size);
> adr = addr;
> while (!feof (f))
> {
> @@ -372,11 +380,7 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> {
> int j;
> if ((adr & (BSIZE - 1)) == 0)
> - {
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX"),
> - (long unsigned) adr);
> - urj_log (URJ_LOG_LEVEL_NORMAL, "\r");
> - }
> + urj_log_progress_tick (adr);
>
> data = 0;
> for (j = 0; j < flash_driver->bus_width; j++)
> @@ -396,14 +400,13 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> write_buffer, write_buffer_count))
> {
> // retain error state
> - return URJ_STATUS_FAIL;
> + return urj_log_progress_done (URJ_STATUS_FAIL);
> }
>
> }
> free (erased);
>
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX\n"),
> - (long unsigned) adr - flash_driver->bus_width);
> + urj_log_progress_done (URJ_STATUS_OK);
>
> flash_driver->readarray (urj_flash_cfi_array);
>
> @@ -414,7 +417,7 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> }
>
> fseek (f, 0, SEEK_SET);
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("verify:\n"));
> + urj_log_progress_init_range (_("program"), addr, addr + st.st_size);
> adr = addr;
> while (!feof (f))
> {
> @@ -434,11 +437,7 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> uint32_t next_adr = adr + flash_driver->bus_width;
>
> if ((adr & 0xFF) == 0)
> - {
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX"),
> - (long unsigned) adr);
> - urj_log (URJ_LOG_LEVEL_NORMAL, "\r");
> - }
> + urj_log_progress_tick (adr);
>
> data = 0;
> for (j = 0; j < flash_driver->bus_width; j++)
> @@ -457,7 +456,7 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> _("addr: 0x%08lX\n verify error:\nread:
> 0x%08lX\nexpected: 0x%08lX\n"),
> (long unsigned) adr, (long unsigned) readed,
> (long unsigned) data);
> - return URJ_STATUS_FAIL;
> + return urj_log_progress_done (URJ_STATUS_FAIL);
> }
> adr = next_adr;
> }
> @@ -467,10 +466,8 @@ urj_flashmem (urj_bus_t *bus, FILE *f, u
> finish condition twice within the loop */
> (void) URJ_BUS_READ_END (bus);
> }
> - urj_log (URJ_LOG_LEVEL_NORMAL, _("addr: 0x%08lX\nDone.\n"),
> - (long unsigned) adr - flash_driver->bus_width);
>
> - return URJ_STATUS_OK;
> + return urj_log_progress_done (URJ_STATUS_OK);
> }
>
> int
> --- src/global/log-error.c (revision 1968)
> +++ src/global/log-error.c (working copy)
> @@ -36,12 +36,14 @@ urj_error_state_t urj_error_state;
>
> static int stderr_vprintf (const char *fmt, va_list ap);
> static int stdout_vprintf (const char *fmt, va_list ap);
> +static int progress (urj_log_progress_t cmd, ...);
>
> urj_log_state_t urj_log_state =
> {
> .level = URJ_LOG_LEVEL_NORMAL,
> .out_vprintf = stdout_vprintf,
> .err_vprintf = stderr_vprintf,
> + .progress = progress,
> };
>
> static int
> @@ -73,6 +75,91 @@ log_printf (int (*p) (const char *, va_l
> return r;
> }
>
> +static int progress (urj_log_progress_t cmd, ...)
> +{
> + static const char spinner[] = {
> + '/', '-', '\\', '|',
> + };
> + static int mode;
> + static unsigned long start, end, len, pos;
> + va_list ap;
> + int ret = URJ_STATUS_OK;
> +
> + va_start (ap, cmd);
> + switch (cmd)
> + {
> + case URJ_LOG_PROGRESS_INIT:
> + {
> + const char *msg;
> + int spacing = 0;
> +
> + mode = va_arg (ap, int);
> + msg = va_arg (ap, const char *);
> + switch (mode)
> + {
> + case 0:
> + spacing = 2;
> + pos = 0;
> + break;
> + case 1:
> + spacing = 1;
> + break;
> + case 2:
> + start = va_arg (ap, unsigned long);
> + end = va_arg (ap, unsigned long);
> + len = end - start;
> + break;
> + default:
> + ret = URJ_STATUS_FAIL;
> + break;
> + }
> +
> + log_printf (urj_log_state.out_vprintf, "\r%s:%*s", msg, spacing, "");
> + break;
> + }
> + case URJ_LOG_PROGRESS_TICK:
> + switch (mode)
> + {
> + case 0:
> + log_printf (urj_log_state.out_vprintf, "\b%c", spinner[pos]);
> + pos = (pos + 1) % sizeof (spinner);
> + break;
> + case 1:
> + log_printf (urj_log_state.out_vprintf, ".");
> + break;
> + case 2:
> + {
> + double curr;
> + int backup;
> + char b[1024];
> +
> + pos = va_arg (ap, unsigned long);
> + curr = (pos - start) * 100;
> + backup = log_printf (urj_log_state.out_vprintf, " %#lx (%u%%)",
> + pos, (unsigned)(curr / len));
> + memset (b, '\b', backup);
> + b[backup] = '\0';
> + log_printf (urj_log_state.out_vprintf, "%s", b);
> + break;
> + }
> + default:
> + ret = URJ_STATUS_FAIL;
> + break;
> + }
> + break;
> + case URJ_LOG_PROGRESS_DONE:
> + {
> + ret = va_arg (ap, int);
> + log_printf (urj_log_state.out_vprintf, " %-20s\n",
> + ret == URJ_STATUS_OK ? _("done") : _("failed"));
> + break;
> + }
> + }
> + va_end (ap);
> +
> + return ret;
> +}
> +
> int
> urj_do_log (urj_log_level_t level, const char *file, size_t line,
> const char *func, const char *fmt, ...)
> ------------------------------------------------------------------------------
> AppSumo Presents a FREE Video for the SourceForge Community by Eric
> Ries, the creator of the Lean Startup Methodology on "Lean Startup
> Secrets Revealed." This video shows you how to validate your ideas,
> optimize your ideas and identify your business strategy.
> http://p.sf.net/sfu/appsumosfdev2dev_______________________________________________
> UrJTAG-development mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/urjtag-development
------------------------------------------------------------------------------
AppSumo Presents a FREE Video for the SourceForge Community by Eric
Ries, the creator of the Lean Startup Methodology on "Lean Startup
Secrets Revealed." This video shows you how to validate your ideas,
optimize your ideas and identify your business strategy.
http://p.sf.net/sfu/appsumosfdev2dev
_______________________________________________
UrJTAG-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/urjtag-development