Compare commits
3 commits
3e85e0257c
...
3760ef7870
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3760ef7870 | ||
|
|
c72ef053ef | ||
|
|
31ed5d8257 |
2 changed files with 138 additions and 29 deletions
|
|
@ -5,8 +5,8 @@ The upboard talks to the irena µC (LPC2148) via UART, implemented in `irena.c`
|
|||
Two gpios are used for reset and flash of the µC.
|
||||
|
||||
TODO
|
||||
- Complete the `numbers[]` array support.
|
||||
- Use `arm_reset()` from `print_status()` in case of error when available.
|
||||
- ✔️ Complete the `numbers[]` array support.
|
||||
- ✔️ Use `arm_reset()` from `print_status()` in case of error when available.
|
||||
- implement `altera_from_file()`:
|
||||
- ARM firmware: base64 upload of data into `flash_buffer`
|
||||
- convert a `.rbf` to a series if `irena` commands.
|
||||
|
|
|
|||
169
irena.c
169
irena.c
|
|
@ -52,7 +52,7 @@ int send_irena_command(const char *c);
|
|||
#define CR_RESET 2
|
||||
#define CR_ONCE 4
|
||||
#define CR_EVER 8
|
||||
#define CR_AT 0xff00
|
||||
#define CR_AT 0xffff00
|
||||
#define CR_AT_CNT 0x0100
|
||||
#define CR_AT_HK 0x0200
|
||||
#define CR_AT_BATE 0x0400
|
||||
|
|
@ -60,6 +60,7 @@ int send_irena_command(const char *c);
|
|||
#define CR_AT_DROT 0x1000
|
||||
#define CR_AT_CROT 0x2000
|
||||
#define CR_AT_SROT 0x4000
|
||||
#define CR_BUFFER 0x10000
|
||||
|
||||
void do_cron(time_t t, int flags, int force);
|
||||
int config_cron(int na, char **av);
|
||||
|
|
@ -777,6 +778,7 @@ struct status {
|
|||
|
||||
static int status_reset_cadence = 3600;
|
||||
static time_t last_status_reset;
|
||||
int arm_reset();
|
||||
|
||||
void print_status(FILE *f, time_t t)
|
||||
{
|
||||
|
|
@ -856,7 +858,8 @@ void print_status(FILE *f, time_t t)
|
|||
if (do_avg && st->reset_delay >= 0 && st->flags & ST_DO_RESET
|
||||
&& last_status_reset + status_reset_cadence < t
|
||||
&& error > st->reset_delay) {
|
||||
if (!tried_reset && !did_reset && !send_irena_command("arm/reset"))
|
||||
if (!tried_reset && !did_reset
|
||||
&& (!arm_reset() || !send_irena_command("arm/reset")))
|
||||
did_reset = 1;
|
||||
tried_reset = 1;
|
||||
if (did_reset) {
|
||||
|
|
@ -1025,6 +1028,7 @@ int gpio_write_value(const char *gpio, int value)
|
|||
|
||||
char reset_gpio[MAX_FN];
|
||||
char eint1_gpio[MAX_FN];
|
||||
int reset_flags = 0;
|
||||
|
||||
void arm_reset_gpio(int polarity)
|
||||
{
|
||||
|
|
@ -1072,12 +1076,16 @@ void arm_reset_uart(int fd, int polarity)
|
|||
return;
|
||||
}
|
||||
|
||||
void arm_reset(int fd, int flags)
|
||||
int arm_reset()
|
||||
{
|
||||
if (flags < 4)
|
||||
arm_reset_uart(fd, flags);
|
||||
else if (flags < 6)
|
||||
arm_reset_gpio(flags & 1);
|
||||
if (reset_flags >= 4 && reset_flags < 6)
|
||||
arm_reset_gpio(reset_flags & 1);
|
||||
else if (i_buf.fd >=0 && reset_flags >= 1 && reset_flags < 4)
|
||||
arm_reset_uart(i_buf.fd, reset_flags);
|
||||
else
|
||||
return -1;
|
||||
fprintf(mout, "Sent hardware RESET, mode %d\n", reset_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_serial_port(const char *name, speed_t baud, int do_reset)
|
||||
|
|
@ -1106,7 +1114,8 @@ int init_serial_port(const char *name, speed_t baud, int do_reset)
|
|||
return -2;
|
||||
}
|
||||
if (do_reset) {
|
||||
arm_reset(i_buf.fd, do_reset);
|
||||
reset_flags = do_reset;
|
||||
arm_reset();
|
||||
if (baud != B38400) {
|
||||
sleep(1);
|
||||
if (cfsetspeed(&tios, baud))
|
||||
|
|
@ -2017,6 +2026,58 @@ void poll_uart(unsigned int ev)
|
|||
}
|
||||
}
|
||||
|
||||
char *poll_response(time_t timeout)
|
||||
{
|
||||
if (!last_irena_command_sent)
|
||||
return 0;
|
||||
timeout += time(0);
|
||||
char *l;
|
||||
do {
|
||||
l = get_line(&i_buf, 1);
|
||||
if (l)
|
||||
process_line(l);
|
||||
} while (last_irena_command_sent && time(0) < timeout);
|
||||
return l;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Send the contents of a file to the flash_buffer and exectute CR_BUFFER in each
|
||||
|
||||
int send_file(const char *fn)
|
||||
{
|
||||
FILE *f = fopen(fn, "r");
|
||||
if (!f) {
|
||||
merror(fn);
|
||||
return -2;
|
||||
}
|
||||
unsigned int buf[128];
|
||||
int n;
|
||||
while ((n = fread(buf, 1, sizeof(buf), f))) {
|
||||
for (int i=0; 4*i < n; i++) {
|
||||
char cmd[64];
|
||||
int retry = 0;
|
||||
snprintf(cmd, 64, "v f[%d]=%u", i, buf[i]);
|
||||
while (retry<3) {
|
||||
while (-2==send_irena_command(cmd))
|
||||
poll_uart(1);
|
||||
char *res = poll_response(2);
|
||||
if (!res)
|
||||
fprintf(mout, "timeout for cmd «%s»\n", cmd);
|
||||
else if (strncmp(res+1, "303", 3))
|
||||
fprintf(mout, "invalid response to «%s» → «%s»\n", cmd, res);
|
||||
else
|
||||
break;
|
||||
poll_uart(0);
|
||||
retry ++;
|
||||
}
|
||||
if (retry >= 3)
|
||||
break;
|
||||
do_cron(0, CR_BUFFER, 1);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sync irena rtc with host clock
|
||||
// Optionally sleep for the rest of the current second
|
||||
|
|
@ -2270,6 +2331,19 @@ int number(char *s, int *i)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int index_number(char *s, int *i)
|
||||
{
|
||||
if (*s != '[') return -1;
|
||||
char *e;
|
||||
int ii = strtol(s+1, &e, 0);
|
||||
if (*e != ']') {
|
||||
fprintf(mout, "invalid index: %s\n", s);
|
||||
return -1;
|
||||
}
|
||||
*i = ii;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int float_number(char *s, double *d)
|
||||
{
|
||||
char *e;
|
||||
|
|
@ -2347,20 +2421,32 @@ struct paths {
|
|||
{.name=0}
|
||||
};
|
||||
|
||||
void print_number(FILE *f, struct numbers *nu)
|
||||
{
|
||||
int n = nu->size;
|
||||
if (!n)
|
||||
n=1;
|
||||
fprintf(f, "\t%s «%s» ", nu->name, nu->doc);
|
||||
for (int i=0; i<n; i++) {
|
||||
if (nu->flags & NU_INT)
|
||||
fprintf(f, " %d", nu->i[i]);
|
||||
else if (nu->flags & NU_DOUBLE)
|
||||
fprintf(f, " %g", nu->d[i]);
|
||||
else if (nu->flags & NU_TIME) {
|
||||
struct tm gm;
|
||||
gmtime_r(nu->t+i, &gm);
|
||||
char tt[] = "1970-01-01T00:00:00Z\0";
|
||||
strftime(tt, sizeof(tt), "%Y-%m-%dT%H:%M:%SZ", &gm);
|
||||
fprintf(f, " %ld %s", nu->t[i], tt);
|
||||
}
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
void print_numbers(FILE *f)
|
||||
{
|
||||
for (struct numbers *nu=numbers; nu->name; nu++)
|
||||
if (nu->flags & NU_INT)
|
||||
fprintf(mout, "\t%s «%s» %d\n", nu->name, nu->doc, *nu->i);
|
||||
else if (nu->flags & NU_DOUBLE)
|
||||
fprintf(mout, "\t%s «%s» %g\n", nu->name, nu->doc, *nu->d);
|
||||
else if (nu->flags & NU_TIME) {
|
||||
struct tm gm;
|
||||
gmtime_r(nu->t, &gm);
|
||||
char tt[] = "1970-01-01T00:00:00Z\0";
|
||||
strftime(tt, sizeof(tt), "%Y-%m-%dT%H:%M:%SZ", &gm);
|
||||
fprintf(mout, "\t%s «%s» %ld %s\n", nu->name, nu->doc, *nu->t, tt);
|
||||
}
|
||||
print_number(f, nu);
|
||||
}
|
||||
|
||||
int process_cmd(char *l);
|
||||
|
|
@ -2433,6 +2519,7 @@ int process_cmd(char *l)
|
|||
"\tcron [«index» [«flags»… [«delay» «cmd»]]]\n"
|
||||
"\tcron force «flags»… [«times»]\n"
|
||||
"\tcron «index» delete\n"
|
||||
"\t«number» [[«index»]] [«value» …]\n"
|
||||
"\n"
|
||||
);
|
||||
print_numbers(mout);
|
||||
|
|
@ -2446,32 +2533,44 @@ int process_cmd(char *l)
|
|||
for (struct numbers *n=numbers; n->name; n++) {
|
||||
if (strcmp(av[0], n->name))
|
||||
continue;
|
||||
if (na>2) {
|
||||
int ii = 0;
|
||||
char **aa = av+1;
|
||||
na--;
|
||||
int nn = n->size;
|
||||
if (!nn)
|
||||
nn=1;
|
||||
if (nn>1 && na>=2 && !index_number(*aa, &ii)) {
|
||||
aa++;
|
||||
na--;
|
||||
}
|
||||
if (ii<0 || na+ii > nn) {
|
||||
if (nn>1)
|
||||
fprintf(mout, "usage: %s [[«i»]] «%s» [… %d items]\n", n->name, n->doc, nn);
|
||||
else
|
||||
fprintf(mout, "usage: %s «%s»\n", n->name, n->doc);
|
||||
return -1;
|
||||
}
|
||||
if (na==2) {
|
||||
|
||||
for (; na && ii<nn; ii++, aa++, na--) {
|
||||
int r=-1;
|
||||
if (n->flags & NU_INT) r = number(av[1], n->i);
|
||||
if (n->flags & NU_DOUBLE) r = float_number(av[1], n->d);
|
||||
if (n->flags & NU_INT) r = number(*aa, n->i+ii);
|
||||
if (n->flags & NU_DOUBLE) r = float_number(*aa, n->d+ii);
|
||||
if (n->flags & NU_TIME) {
|
||||
if (!strcmp(av[1], "now")) {
|
||||
*n->t = time(0);
|
||||
if (!strcmp(*aa, "now")) {
|
||||
n->t[ii] = time(0);
|
||||
r = 0;
|
||||
}
|
||||
else {
|
||||
int t=0;
|
||||
r = number(av[1], &t);
|
||||
r = number(*aa, &t);
|
||||
if (!r)
|
||||
*n->t = t;
|
||||
n->t[ii] = t;
|
||||
}
|
||||
}
|
||||
if (r)
|
||||
return -1;
|
||||
}
|
||||
if (n->flags & NU_INT) fprintf(mout, "%s %d\n", n->name, *n->i);
|
||||
if (n->flags & NU_DOUBLE) fprintf(mout, "%s %g\n", n->name, *n->d);
|
||||
if (n->flags & NU_TIME) fprintf(mout, "%s %ld\n", n->name, *n->t);
|
||||
print_number(mout, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2504,6 +2603,14 @@ int process_cmd(char *l)
|
|||
return process_script(av[1]);
|
||||
}
|
||||
|
||||
if (!strcmp(av[0], "sendfile")) {
|
||||
if (na!=2) {
|
||||
fprintf(mout, "usage: sendfile «filename»\n");
|
||||
return -1;
|
||||
}
|
||||
return send_file(av[1]);
|
||||
}
|
||||
|
||||
if (!strcmp(av[0], "uart")) {
|
||||
speed_t baud = B921600;
|
||||
int do_reset = 0;
|
||||
|
|
@ -2702,6 +2809,8 @@ int config_cron(int na, char **av)
|
|||
flags |= CR_ONCE;
|
||||
else if (!strcmp(av[ai], "ever"))
|
||||
flags |= CR_EVER;
|
||||
else if (!strcmp(av[ai], "buffer"))
|
||||
flags |= CR_BUFFER;
|
||||
else if (!strcmp(av[ai], "got_hk"))
|
||||
flags |= CR_AT_HK;
|
||||
else if (!strcmp(av[ai], "got_cntr"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue