--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <ao.h>
+#include <ao_lisp.h>
+#include <ao_flash.h>
+
+extern uint8_t __flash__[];
+
+/* saved variables to rebuild the heap
+
+ ao_lisp_atoms
+ ao_lisp_frame_global
+ */
+
+int
+ao_lisp_os_save(void)
+{
+ int i;
+
+ for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) {
+ uint32_t *dst = (uint32_t *) &__flash__[i];
+ uint32_t *src = (uint32_t *) &ao_lisp_pool[i];
+
+ ao_flash_page(dst, src);
+ }
+ return 1;
+}
+
+int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset)
+{
+ memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save));
+ return 1;
+}
+
+int
+ao_lisp_os_restore(void)
+{
+ memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL);
+ return 1;
+}
#ifdef AO_LISP_SAVE
struct ao_lisp_os_save {
- ao_poly ao_lisp_atoms;
- ao_poly ao_lisp_globals;
+ ao_poly atoms;
+ ao_poly globals;
+ uint16_t const_checksum;
+ uint16_t const_checksum_inv;
};
-#define AO_LISP_POOL (AO_LISP_POOL_TOTAL - sizeof (struct ao_lisp_os_save))
+#define AO_LISP_POOL_EXTRA (sizeof(struct ao_lisp_os_save))
+#define AO_LISP_POOL ((int) (AO_LISP_POOL_TOTAL - AO_LISP_POOL_EXTRA))
int
ao_lisp_os_save(void);
+int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset);
+
int
ao_lisp_os_restore(void);
#define _ao_lisp_atom_eval _atom("eval")
#define _ao_lisp_atom_read _atom("read")
#define _ao_lisp_atom_eof _atom("eof")
+#define _ao_lisp_atom_save _atom("save")
+#define _ao_lisp_atom_restore _atom("restore")
#else
#include "ao_lisp_const.h"
#ifndef AO_LISP_POOL
-#define AO_LISP_POOL 16384
+#define AO_LISP_POOL 3072
#endif
-extern uint8_t ao_lisp_pool[AO_LISP_POOL];
+extern uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA];
#endif
/* Primitive types */
return 0;
}
+#define AO_FEC_CRC_INIT 0xffff
+
+static inline uint16_t
+ao_fec_crc_byte(uint8_t byte, uint16_t crc)
+{
+ uint8_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ if (((crc & 0x8000) >> 8) ^ (byte & 0x80))
+ crc = (crc << 1) ^ 0x8005;
+ else
+ crc = (crc << 1);
+ byte <<= 1;
+ }
+ return crc;
+}
+
+uint16_t
+ao_fec_crc(const uint8_t *bytes, uint8_t len)
+{
+ uint16_t crc = AO_FEC_CRC_INIT;
+
+ while (len--)
+ crc = ao_fec_crc_byte(*bytes++, crc);
+ return crc;
+}
+
int
main(int argc, char **argv)
{
printf("extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n");
printf("#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms));
printf("#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(ao_lisp_frame_global));
+ printf("#define ao_lisp_const_checksum ((uint16_t) 0x%04x)\n", ao_fec_crc(ao_lisp_const, ao_lisp_top));
for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) {
char *n = a->name, c;
#undef AO_LISP_POOL
#define AO_LISP_POOL AO_LISP_POOL_CONST
#else
-uint8_t ao_lisp_pool[AO_LISP_POOL] __attribute__((aligned(4)));
+uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA] __attribute__((aligned(4)));
#endif
#if 0
ao_poly
ao_lisp_save(struct ao_lisp_cons *cons)
{
+ if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0))
+ return AO_LISP_NIL;
+
#ifdef AO_LISP_SAVE
struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL];
ao_lisp_collect();
- os->ao_lisp_atoms = ao_lisp_atom_poly(ao_lisp_atoms);
- os->ao_lisp_globals = ao_lisp_frame_poly(ao_lisp_frame_global);
+ os->atoms = ao_lisp_atom_poly(ao_lisp_atoms);
+ os->globals = ao_lisp_frame_poly(ao_lisp_frame_global);
+ os->const_checksum = ao_lisp_const_checksum;
+ os->const_checksum_inv = ~ao_lisp_const_checksum;
+
if (ao_lisp_os_save())
return _ao_lisp_atom_t;
#endif
ao_poly
ao_lisp_restore(struct ao_lisp_cons *cons)
{
+ if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0))
+ return AO_LISP_NIL;
+
#ifdef AO_LISP_SAVE
+ struct ao_lisp_os_save save;
struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) &ao_lisp_pool[AO_LISP_POOL];
+ if (!ao_lisp_os_restore_save(&save, AO_LISP_POOL))
+ return ao_lisp_error(AO_LISP_INVALID, "header restore failed");
+
+ if (save.const_checksum != ao_lisp_const_checksum ||
+ save.const_checksum_inv != (uint16_t) ~ao_lisp_const_checksum)
+ {
+ return ao_lisp_error(AO_LISP_INVALID, "image is corrupted or stale");
+ }
+
if (ao_lisp_os_restore()) {
- ao_lisp_atoms = ao_lisp_poly_atom(os->ao_lisp_atoms);
- ao_lisp_frame_global = ao_lisp_poly_frame(os->ao_lisp_globals);
+ ao_lisp_atoms = ao_lisp_poly_atom(os->atoms);
+ ao_lisp_frame_global = ao_lisp_poly_frame(os->globals);
/* Clear the eval global variabls */
ao_lisp_eval_clear_globals();
return 1;
}
+int
+ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset)
+{
+ FILE *restore = fopen(save_file, "r");
+ size_t ret;
+
+ if (!restore) {
+ perror(save_file);
+ return 0;
+ }
+ fseek(restore, offset, SEEK_SET);
+ ret = fread(save, sizeof (struct ao_lisp_os_save), 1, restore);
+ fclose(restore);
+ if (ret != 1)
+ return 0;
+ return 1;
+}
+
int
ao_lisp_os_restore(void)
{
(patom "\033[2J" nil)
)
-(defun test ()
- (clear)
- (move-to 30 12)
- (patom "hello, world")
- (move-to 0 19)
- )
-
(setq stack '("*" "**" "***" "****" "*****" "******" "*******"))
(setq stacks nil)
(defun display-string (x y str)
- (move-to x y)
(move-to x y)
(patom str)
)