Compare commits

..

6 commits

Author SHA1 Message Date
Stephan I. Böttcher
36dbe8dcb7 set_clock sleep with poll_uart every 100ms 2023-11-19 01:15:47 +01:00
Stephan I. Böttcher
c67d1f0455 sendfile drop 2023-11-19 00:46:21 +01:00
Stephan I. Böttcher
e6958c31d0 sendfile fn cmd 2023-11-19 00:24:47 +01:00
Stephan I. Böttcher
8ea5fe76a3 fix set_clock config 2023-11-18 23:12:37 +01:00
Stephan I. Böttcher
bee3380a95 in_prompt 2023-11-18 23:07:03 +01:00
Stephan I. Böttcher
7fc84c0996 call d3dinit.rc after 60 seconds 2023-11-18 22:08:54 +01:00
3 changed files with 117 additions and 78 deletions

3
d3d.rc
View file

@ -2,7 +2,6 @@
path reset_gpio /run/gpio/Reset/value path reset_gpio /run/gpio/Reset/value
path eint1_gpio /run/gpio/EINT1/value path eint1_gpio /run/gpio/EINT1/value
uart /dev/ttyS1 gpio uart /dev/ttyS1 gpio
clock_sync 3600
fct_min_data 16 fct_min_data 16
fct_max_cadence 2 fct_max_cadence 2
fct 32 fct 32
@ -10,4 +9,4 @@ statusfile d3d/irena-status
datafile d3d/irena-%Y-%m-%dT%H:%M:%SZ.dat datafile d3d/irena-%Y-%m-%dT%H:%M:%SZ.dat
counterfile d3d/irena-%Y-%m-%dT%H:%M:%SZ.hst counterfile d3d/irena-%Y-%m-%dT%H:%M:%SZ.hst
socket unix irena-control interactive force socket unix irena-control interactive force
cron next init 60 irena pres/inj cron next init 60 script d3dinit.rc

4
d3dinit.rc Normal file
View file

@ -0,0 +1,4 @@
irena pres/inj
irena v rtc_drift[3] = 0x10700
clock_sync 3600
set_clock drift config

178
irena.c
View file

@ -29,12 +29,21 @@ const char version[] = "$Id$";
FILE *mout; FILE *mout;
int maintainance = 0; int maintainance = 0;
int verbosity[2] = {1,1}; int verbosity[2] = {1,1};
int in_prompt;
void check_prompt()
{
if (in_prompt==1) {
fprintf(mout, "\n");
in_prompt = 2;
}
}
static inline void silent(int v) { if (verbosity[0] < v) verbosity[1] = 0; } static inline void silent(int v) { if (verbosity[0] < v) verbosity[1] = 0; }
static inline void unsilent() { verbosity[1] = verbosity[0]; } static inline void unsilent() { verbosity[1] = verbosity[0]; }
static inline void loud(int v) { if (v > verbosity[0]) verbosity[1] = v; } static inline void loud(int v) { if (v > verbosity[0]) verbosity[1] = v; }
static inline int verbose(int v) { v = verbosity[1] >= v; unsilent(); return v; } static inline int verbose(int v) { v = verbosity[1] >= v; unsilent(); if (v) check_prompt(); return v; }
// replacement for perror() // replacement for perror()
void merror(const char *s) void merror(const char *s)
@ -941,10 +950,10 @@ int config_status(int na, char **av)
} }
} }
fprintf(mout, "%s %s[%u] %g %g %g %g %s tau %d flags 0x%04x reset %d\n", fprintf(mout, "%s %s[%u] %g %g %g %g %s tau %d reset %d flags 0x%04x\n",
av[0], st->name, index, av[0], st->name, index,
st->limits[0], st->limits[1], st->limits[2], st->limits[3], st->limits[0], st->limits[1], st->limits[2], st->limits[3],
st->units, st->tau, st->flags, st->reset_delay); st->units, st->tau, st->reset_delay, st->flags);
return 0; return 0;
} }
@ -977,6 +986,16 @@ struct line_buffer {
static inline static inline
void buffer_reset(struct line_buffer *b) { b->size = b->read = 0; } void buffer_reset(struct line_buffer *b) { b->size = b->read = 0; }
void reprint_line(struct line_buffer *b)
{
// in case the prompt was garbled
int n = read(b->fd, b->buf + b->size, 4095 - b->size);
if (n>0)
b->size += n;
b->buf[b->size] = 0;
fprintf(mout, "%.*s", b->size - b->read, b->buf + b->read);
}
char *get_line(struct line_buffer *b, unsigned int ev) char *get_line(struct line_buffer *b, unsigned int ev)
{ {
if (b->fd < 0) if (b->fd < 0)
@ -1092,6 +1111,7 @@ int arm_reset()
arm_reset_uart(i_buf.fd, reset_flags); arm_reset_uart(i_buf.fd, reset_flags);
else else
return -1; return -1;
if (verbose(0))
fprintf(mout, "Sent hardware RESET, mode %d\n", reset_flags); fprintf(mout, "Sent hardware RESET, mode %d\n", reset_flags);
return 0; return 0;
} }
@ -1162,10 +1182,9 @@ int split(char *l, int n, char *sp[])
return i; return i;
} }
void unsplit(char *l, int n) void unsplit(char *s, int n)
{ {
int i = 1; int i = 1;
char *s = l;
while (i<n) { while (i<n) {
s = index(s, 0); s = index(s, 0);
*s = ' '; *s = ' ';
@ -1223,6 +1242,7 @@ int base64_decode(const char *l, unsigned char *b, size_t n)
else if (!i && (!c || c=='\n')) else if (!i && (!c || c=='\n'))
return m; return m;
else if (c&0x80 || !bb[i] && c!='A') { else if (c&0x80 || !bb[i] && c!='A') {
if (verbose(0))
fprintf(mout, "Base64 format error: %s\n", l); fprintf(mout, "Base64 format error: %s\n", l);
return 0; return 0;
} }
@ -1288,7 +1308,7 @@ int base85_decode(const char *l, unsigned char *b, size_t n)
l++; l++;
int ll = base85_decode1(l, (unsigned int*)(b+m)); int ll = base85_decode1(l, (unsigned int*)(b+m));
if (!ll) { if (!ll) {
if (*l && verbose(2)) if (*l && verbose(0))
fprintf(mout, "invalid base85: «%s»\n", l); fprintf(mout, "invalid base85: «%s»\n", l);
return m; return m;
} }
@ -2168,64 +2188,34 @@ static inline unsigned char b64_chr(unsigned int c)
return e[c&0x3f]; return e[c&0x3f];
} }
int send_file_64(const char *fn) int process_cmd(char *l);
int send_file(const char *fn, const char *cfmt, unsigned int drop)
{ {
FILE *f = fopen(fn, "r"); // cfmt must have at most two %i formats.
if (!f) { const char *s = cfmt;
merror(fn); int i= 0;
return -2; while (s) {
s = index(s, '%');
s++;
if (*s=='%') {
s++;
continue;
} }
unsigned char buf[512]; if (i >= 2) {
int n; if (verbose(-1))
while ((n = fread(buf, 1, sizeof(buf), f))) { fprintf(mout, "more than two in parameters «%s»\n", cfmt);
if (n<sizeof(buf)) return -3;
memset(buf+n, 0, sizeof(buf)-n);
n = sizeof(buf);
n = (n+3) & ~3; // NOP
for (int i=0; i < n; ) {
char cmd[64];
int retry = 0;
int c = snprintf(cmd, 64, "v f[%d]=:=", i>>2);
while (c<58) {
int nn = -i & 3;
if (c < 54 || nn > n-i)
nn = n-i;
if (!nn)
break;
unsigned char a1, a2=0, a3=0;
a1 = buf[i++];
if (nn>1) a2 = buf[i++];
if (nn>2) a3 = buf[i++];
cmd[c++] = b64_chr(a1>>2);
cmd[c++] = b64_chr((a1<<4) | (a2>>4));
cmd[c++] = nn>1 ? b64_chr((a2<<2) | (a3>>6)) : '=';
cmd[c++] = nn>2 ? b64_chr(a3) : '=';
} }
cmd[c++] = 0; while (index(".-+#0123456789", *s)) s++;
while (retry<3) { if (!*s || !index("diuoOxX", *s)) {
loud(2); if (verbose(-1))
while (-2==send_irena_command(cmd)) fprintf(mout, "invalid format «%s»\n", cfmt);
poll_uart(1); return -3;
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) i++;
break;
}
do_cron(0, CR_BUFFER, 1);
}
return -1;
} }
int send_file_85(const char *fn)
{
FILE *f = fopen(fn, "r"); FILE *f = fopen(fn, "r");
if (!f) { if (!f) {
merror(fn); merror(fn);
@ -2233,10 +2223,19 @@ int send_file_85(const char *fn)
} }
unsigned int buf[128]; unsigned int buf[128];
int n; int n;
int a = 0;
while ((n = fread(buf, 1, sizeof(buf), f))) { while ((n = fread(buf, 1, sizeof(buf), f))) {
if (n<sizeof(buf)) if (n<sizeof(buf))
memset(buf+n, 0, sizeof(buf)-n); memset(buf+n, 0, sizeof(buf)-n);
n = sizeof(buf); // Drop blocks that are only 0xff, those
// are unused blocks in the flash filesystem.
int d = 1;
if (drop) while (d<128 && buf[d]==buf[0]) d++;
if (d>=128 && buf[0]==0xffffffff) {
if (verbose(2))
fprintf(mout, "dropping block %d\n", a/128);
continue;
}
for (int i=0; i<128; ) { for (int i=0; i<128; ) {
char cmd[64]; char cmd[64];
int retry = 0; int retry = 0;
@ -2258,9 +2257,18 @@ int send_file_85(const char *fn)
retry ++; retry ++;
} }
if (retry >= 3) if (retry >= 3)
break; return -1;
}
if (cfmt) {
char cmd[128];
int cs = snprintf(cmd, 128, cfmt, a, n);
if (cs <= 127)
process_cmd(cmd);
else if (verbose(-1))
fprintf(mout, "sendfile format too long «%s»\n", cmd);
} }
do_cron(0, CR_BUFFER, 1); do_cron(0, CR_BUFFER, 1);
a += n;
} }
return -1; return -1;
} }
@ -2274,7 +2282,16 @@ int set_clock(int do_sleep)
time_t t = 0; time_t t = 0;
if (do_sleep) { if (do_sleep) {
struct timespec ts; struct timespec ts;
poll_uart(1);
if (!clock_gettime(CLOCK_REALTIME, &ts)) { if (!clock_gettime(CLOCK_REALTIME, &ts)) {
while (ts.tv_nsec < 750000000) {
ts.tv_nsec += 100000000;
clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &ts, 0);
if (verbose(2))
fprintf(mout, "slept 100ms ns=%lu\n", ts.tv_nsec);
poll_uart(1);
clock_gettime(CLOCK_REALTIME, &ts);
}
ts.tv_sec++; ts.tv_sec++;
t = ts.tv_sec; t = ts.tv_sec;
ts.tv_nsec=0; ts.tv_nsec=0;
@ -2344,6 +2361,7 @@ const char *cmd_socket_name() {
int close_cmd_socket() int close_cmd_socket()
{ {
if (cmd_socket_fd >= 0) { if (cmd_socket_fd >= 0) {
if (verbose(1))
fprintf(mout, "closing cmd socket: «%s»\n", cmd_socket_name()); fprintf(mout, "closing cmd socket: «%s»\n", cmd_socket_name());
epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cmd_socket_fd, 0); epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cmd_socket_fd, 0);
close(cmd_socket_fd); close(cmd_socket_fd);
@ -2604,7 +2622,7 @@ struct numbers {
{.name="fct_packets", .doc="packets", .i=&fct_packets, .flags=NU_INT}, {.name="fct_packets", .doc="packets", .i=&fct_packets, .flags=NU_INT},
{.name="clock_sync", .doc="seconds", .u=&clock_cadence, .flags=NU_INT}, {.name="clock_sync", .doc="seconds", .u=&clock_cadence, .flags=NU_INT},
{.name="clock_mod", .doc="seconds", .u=&clock_modulus, .flags=NU_INT}, {.name="clock_mod", .doc="seconds", .u=&clock_modulus, .flags=NU_INT},
{.name="clock_sleep", .doc="bool", .i=&clock_sleep, .flags=NU_INT}, {.name="clock_sleep", .doc="(1=sleep,2=drift)", .i=&clock_sleep, .flags=NU_INT},
{.name="reset_cadence", .doc="seconds", .i=&status_reset_cadence, .flags=NU_INT}, {.name="reset_cadence", .doc="seconds", .i=&status_reset_cadence, .flags=NU_INT},
{.name="last_reset", .doc="time", .t=&last_status_reset, .flags=NU_TIME}, {.name="last_reset", .doc="time", .t=&last_status_reset, .flags=NU_TIME},
{.name="init_time", .doc="time", .t=&init_time, .flags=NU_TIME}, {.name="init_time", .doc="time", .t=&init_time, .flags=NU_TIME},
@ -2659,7 +2677,6 @@ void print_numbers(FILE *f)
print_number(f, nu); print_number(f, nu);
} }
int process_cmd(char *l);
int process_script(const char *fn) int process_script(const char *fn)
{ {
static int recursion = 0; static int recursion = 0;
@ -2699,6 +2716,7 @@ int process_cmd(char *l)
int na = split(l, 10, av); int na = split(l, 10, av);
if (!na) if (!na)
return 0; return 0;
check_prompt();
if (verbose(2) || !strcmp(av[0], "echo")) { if (verbose(2) || !strcmp(av[0], "echo")) {
fprintf(mout, "CMD:"); fprintf(mout, "CMD:");
for (int i=0; i<na; i++) for (int i=0; i<na; i++)
@ -2731,6 +2749,7 @@ int process_cmd(char *l)
"\tcron [«index» [«flags»… [«delay» «cmd»]]]\n" "\tcron [«index» [«flags»… [«delay» «cmd»]]]\n"
"\tcron force «flags»… [«times»]\n" "\tcron force «flags»… [«times»]\n"
"\tcron «index» delete\n" "\tcron «index» delete\n"
"\tsendfile «filename» [drop] [«command»]\n"
"\t«number» [[«index»]] [«value» …]\n" "\t«number» [[«index»]] [«value» …]\n"
"\n" "\n"
); );
@ -2816,11 +2835,18 @@ int process_cmd(char *l)
} }
if (!strcmp(av[0], "sendfile")) { if (!strcmp(av[0], "sendfile")) {
if (na!=2) { char *cmd = 0;
fprintf(mout, "usage: sendfile «filename»\n"); int drop = 0;
return -1; int i = 2;
if (na>2 && !strcmp(av[2], "drop")) {
drop = 1;
i++;
} }
return send_file_85(av[1]); if (na>i) {
unsplit(av[i], na-i);
cmd = av[i];
}
return send_file(av[1], cmd, drop);
} }
if (!strcmp(av[0], "uart")) { if (!strcmp(av[0], "uart")) {
@ -2877,7 +2903,7 @@ int process_cmd(char *l)
else if (!strcmp(av[1], "drift")) do_sleep = 2; else if (!strcmp(av[1], "drift")) do_sleep = 2;
else if (!strcmp(av[1], "config")) config = 1; else if (!strcmp(av[1], "config")) config = 1;
else do_sleep = -1; else do_sleep = -1;
if (na>3 || na>2 && (!do_sleep || strcmp(av[1], "config"))) if (na>3 || na>2 && (!do_sleep || strcmp(av[2], "config")))
do_sleep = -1; do_sleep = -1;
if (do_sleep < 0) { if (do_sleep < 0) {
fprintf(mout, "usage: set_clock [sleep|drift] [config]\n"); fprintf(mout, "usage: set_clock [sleep|drift] [config]\n");
@ -3145,6 +3171,7 @@ int main(int argc, char **argv)
if (isatty(0) && isatty(2)) { if (isatty(0) && isatty(2)) {
prompt = "IRENA> "; prompt = "IRENA> ";
fprintf(mout, prompt); fprintf(mout, prompt);
in_prompt = 1;
} }
reset_priorities(); reset_priorities();
@ -3160,8 +3187,8 @@ int main(int argc, char **argv)
int n = epoll_wait(epoll_fd, eev, 2, 1000); int n = epoll_wait(epoll_fd, eev, 2, 1000);
time_t t = time(0); time_t t = time(0);
for (int i=0; i<n; i++) { for (int i=0; i<n; i++) {
if (eev[i].events != EPOLLIN) if (eev[i].events != EPOLLIN && verbose(2))
debug("epoll: fd=%d events=0x%x\n", eev[i].data.fd, eev[i].events); fprintf(mout, "epoll: fd=%d events=0x%x\n", eev[i].data.fd, eev[i].events);
if (eev[i].data.fd == cmd_socket_fd) if (eev[i].data.fd == cmd_socket_fd)
accept_cmd_socket(&s_buf, cmd_socket_fd); accept_cmd_socket(&s_buf, cmd_socket_fd);
else if (eev[i].data.fd == s_buf.fd) { else if (eev[i].data.fd == s_buf.fd) {
@ -3177,14 +3204,23 @@ int main(int argc, char **argv)
poll_uart(eev[i].events); poll_uart(eev[i].events);
} }
else { else {
char *l = get_line(&c_buf, eev[i].events); int do_read = eev[i].events;
if (prompt && in_prompt==2 && do_read) {
fprintf(mout, prompt);
reprint_line(&c_buf);
in_prompt = 1;
do_read = 0;
}
char *l = get_line(&c_buf, do_read);
while (l) { while (l) {
in_prompt = 0;
process_cmd(l); process_cmd(l);
if (prompt) { if (prompt) {
if (maintainance) if (maintainance)
fprintf(stderr, "M:%s", prompt); fprintf(stderr, "M:%s", prompt);
else else
fprintf(stderr, prompt); fprintf(stderr, prompt);
in_prompt = 1;
} }
l = get_line(&c_buf, 0); l = get_line(&c_buf, 0);
} }