-
Hi,
I have a relatively big codebase right now and I'm not sure what causes this error:
Unable to create string as not enough memory
I guess I'm having trouble while reading from
FlashEEPROM
with the following class:export pack = (x) -> JSON.stringify x export unpack = (wire-data) -> try x = JSON.parse wire-data throw if x is void return x catch console.log "Error on unpacking: ", e console.log "wire data: ", wire-data throw "Error on unpacking" export !function Config file-no self = this @file-no = file-no @f = new (require "FlashEEPROM")(0x076000) @f.endAddr = @f.addr + 1024 @write-count = 0 @write = (data) !-> if @write-count++ > 10 @f.cleanup! @write-count = 0 @f.write self.file-no, pack data @read = -> try data = E.to-string @f.read self.file-no return unpack data catch console.log "ERROR CONFIG READ: ", e console.log "raw data read: ", data console.log "dump: ", @file-no
Here is the Javascript output of above code:
var pack, unpack, out$ = typeof exports != 'undefined' && exports || this; out$.pack = pack = function(x){ return JSON.stringify(x); }; out$.unpack = unpack = function(wireData){ var x, e; try { x = JSON.parse(wireData); if (x === void 8) { throw null; } return x; } catch (e$) { e = e$; console.log("Error on unpacking: ", e); console.log("wire data: ", wireData); throw "Error on unpacking"; } }; out$.Config = Config; function Config(fileNo){ var self; self = this; this.fileNo = fileNo; this.f = new (require("FlashEEPROM"))(0x076000); this.f.endAddr = this.f.addr + 1024; this.writeCount = 0; this.write = function(data){ if (this.writeCount++ > 10) { this.f.cleanup(); this.writeCount = 0; } this.f.write(self.fileNo, pack(data)); }; this.read = function(){ var data, e; try { data = E.toString(this.f.read(self.fileNo)); return unpack(data); } catch (e$) { e = e$; console.log("ERROR CONFIG READ: ", e); console.log("raw data read: ", data); return console.log("dump: ", this.fileNo); } }; }
I'm trying to use this code as follows:
a = new Config 1 inc-input = -> try x = a.read! throw if isNaN x catch console.log "error reading input counter: ", e x = 0 a.write ++x x sim2 = !-> <- :lo(op) -> console.log inc-input! <- sleep 5ms lo(op)
...the Javascript:
var a, incInput, sim2; a = new Config(1); incInput = function(){ var x, e; try { x = a.read(); if (isNaN(x)) { throw null; } } catch (e$) { e = e$; console.log("error reading input counter: ", e); x = 0; } a.write(++x); return x; }; sim2 = function(){ (function lo(op){ console.log(incInput()); return sleep(5, function(){ return lo(op); }); })(function(){}); };
The error is:
Error on unpacking: null wire data: undefined ERROR CONFIG READ: Error on unpacking raw data read: undefined dump: 1 144 145 146 147 ERROR: Out of Memory! WARNING: Unable to create string as not enough memory ERROR: Error processing Serial data handler - removing it. Execution Interrupted during event processing. at line 1 col 148 ....flash.read(a,r.addr+4),h==e))){if(r.end+e.length+4>=this.en... ^ in function "write" called from line 1 col 89 ...is.f.write(n.fileNo,pack(e)) in function "write" called from line 1 col 81 ...g.read(),t.set),cfg.write(o),inpCounter.write(o.coinInpRx),o... ^ in function called from system 148 149 150 151 152
I expect the
sim2()
function to increment flash memory area by 1 in every 50 ms and this is what happens most of the time. But sometimes, (in a random order of power cycles) itConfig.read()
throws an error and memory can not be read.Is there anything I might misunderstand about usage of
FlashEEPROM
? -
There was a near-miss of RTFM issue :)
I found this in the documentation: http://www.espruino.com/run_code_from_eeprom#line=8
-
@allObjects This is exactly my plan. I think I can implement such a "Host" (a
bootloader
, or avm kernel thing
) if I could selectively load the code from specific location.On second thoughts: I can use FlashEEPROM. Then, I could write a code that will behave like a console (like
wiflash
does) and will write everything to the EEPROM. Upon a boot process, I could read the EEPROM location and directlyeval
uate these codes; which will exactly simulate whatload()
does.Only difference is, I can save to and load from exactly where I want.
Hmm. Let me try something out. I'll get back to you.
-
@Wilberforce Yes, I've seen that module but it was too late because I've written my own toolset way before I've met Espruino (during which I was dealing with micropython). But the node-espruino doesn't offer such a fallback mechanism anyway.
-
I'm making a plan for such a scenario:
- Think that I developed an application, wrote it to the device, tested it, and send to the field when it's ready.
- It turns out, my application had a bug.
- I have a very very good idea(!) that the problem is just the
var x = 1;
, it should bevar x = {1}
(watch the typo) - I send the code to the device, and the device is bricked now and I have no option to fix the last wrong app...
My plan as a precaution is the following:
- I can send this untested code with a mark to indicate "to be tested",
- device would download and save it,
- make it loaded on next reboot, and
- watch for a specific "heartbeat" sign (for example, I can set a timeout for a specific FlashEEPROM location value and set the "OK" value over socket connection, which will guarantee that my second application boots and connects correctly).
- If no heartbeat is found within a timeout, then old code will be loaded and new code will be discarded by the device (
bootloader
) itself.
- Think that I developed an application, wrote it to the device, tested it, and send to the field when it's ready.
-
Hi,
I want to add an option to my espruino toolset that will support a fallback app code mechanism when uploading code by both wifi and uart interfaces.
I know there is Wifi Remote Console code available already, so there is only a fallback mechanism left to implement.
When I upload a new code, my
bootloader
will boot from newly uploaded code. If some kind of heartbeat is not found for a while, it will reboot and load the last known good code.So the question is, how can I save/load a code to/from from a specific location of EEprom?
-
-
As I clearly understand that you are willing to keep things clear and tidy, you require every post to be sent over its appropriate channel.
So, what purpose are the forums for? What we can manage with a forum where we can not with a good bug tracker, like Github's?
As Jose Valim says about his Elixir, some may consider something as a bug and some other does not.For example, I do consider poor error messages, poor documentation, long documentation, long code requirement, small set of examples as a bug in my projects. What is a bug according to you?
Additionally, I have no distinct separation between code and documentation. So, if a bug is related to code, it is also related with the documentation and vice versa. If it wouldn't, documentation generators (like Doxygen) couldn't exist in the first place.
-
-
Regarding to your explanations, I thought I could write a simple function to build an event-like functionality that uses
setWatch(...)
under the hood, and I planned to ask "can we define a virtual pin where we cansetWatch
?" later on, but I couldn't make a pin triggered via software because it seemssetWatch
is cancelled on a pin that is configured asoutput
andPin.write()
sets a pin's mode as "output".So I ended up defining some simple functions to handle some simple events:
# application do i = 3 console.log td!, "start" <- :lo(op) -> console.log td!, "hi #{i}" i-- <- wait-for \something if i is 0 op!;return # break lo(op) <- sleep 1500ms <- :lo(op) -> console.log td!, "hello #{i}" i++ if i is 3 op!;return # break <- sleep 1000ms lo(op) <- sleep 0 console.log td!, "heyy" do a = 5 <- :lo(op) -> console.log td!, "this runs in parallel!", a a-- go \something if a is 0 op!;return # break <- sleep 500ms lo(op)
The output is:
0ms : start 2ms : hi 3 3ms : this runs in parallel! 5 4ms : hi 2 505ms : this runs in parallel! 4 505ms : hi 1 1007ms : this runs in parallel! 3 1508ms : this runs in parallel! 2 2009ms : this runs in parallel! 1 2508ms : hello 0 3510ms : hello 1 4510ms : hello 2 4512ms : heyy
My current problem seems to be solved now. I can write the code in the way I wanted to without using ES6 specific properties of Javascript.
Hint: You can compile whole code into Javascript online at Livescript.net
-
This is best I can do with Livescript:
sleep = (ms, f) !-> set-timeout f, ms do-something! <- :lo(op) -> x = do-something-else! if x is 0 op!; return <- sleep 100ms lo(op) do-another-thing!
More generally, a sequental-style, "multi-threaded" code could be written in Livescript as follows:
st = new Date! .get-time! td = -> (new Date! .get-time! - st) + "ms :" sleep = (ms, f) !-> set-timeout f, ms do i = 3 console.log td!, "start" <- :lo(op) -> console.log td!, "hi #{i}" i := i - 1 if i is 0 op!;return <- sleep 1000ms lo(op) <- sleep 1500ms <- :lo(op) -> console.log td!, "hello #{i}" i := i + 1 if i is 3 op!;return <- sleep 1000ms lo(op) console.log td!, "heyy" do a = 5 <- :lo(op) -> console.log td!, "this runs in parallel!", a a := a - 1 if a is 0 op!;return <- sleep 500ms lo(op)
Output:
0ms : start 2ms : hi 3 4ms : this runs in parallel! 5 506ms : this runs in parallel! 4 1004ms : hi 2 1009ms : this runs in parallel! 3 1512ms : this runs in parallel! 2 2007ms : hi 1 2015ms : this runs in parallel! 1 3510ms : hello 0 4514ms : hello 1 5517ms : hello 2 5520ms : heyy
Compiled JS:
var st, td, sleep, i, a; st = new Date().getTime(); td = function(){ return (new Date().getTime() - st) + "ms :"; }; sleep = function(ms, f){ setTimeout(f, ms); }; i = 3; console.log(td(), "start"); (function lo(op){ console.log(td(), "hi " + i); i = i - 1; if (i === 0) { op(); return; } return sleep(1000, function(){ return lo(op); }); })(function(){ return sleep(1500, function(){ return function lo(op){ console.log(td(), "hello " + i); i = i + 1; if (i === 3) { op(); return; } return sleep(1000, function(){ return lo(op); }); }(function(){ return console.log(td(), "heyy"); }); }); }); a = 5; (function lo(op){ console.log(td(), "this runs in parallel!", a); a = a - 1; if (a === 0) { op(); return; } return sleep(500, function(){ return lo(op); }); })(function(){});
-
Umm... Livescript compiler is smart, but I don't think It's that far :)
For now, it's best to make these waits via callbacks; but as @allObjects mentioned, this easily leads to a callback hell... Livescript makes this problem solved a little bit easier, but that's what can be done without a serious hack.
Well, it seems I won the big bounty :)
Yes, Python can be multithreaded, but there are many coroutine libraries exist (including Gevent, which is what we use heavily in our DCS library). Gevent is a kind of "hack" in Python and works great. (Guido Van Rossum (the author of Python) does not like gevent, though. He tries to make something with similar practicability with a library called
asyncio
which is mostly influenced by the Twisted project (a very popular networking library in Python) which is mostly influenced by Javascript, which is... Yeah, Espruino already implemented! :) So I thought maybe this is possible in Javascript.I tried to read your "sequencer" code but I'm not able to, it's probably because I don't know Javascript that much. But I'll try to read it again, it might be the key of the solution in my case.
-
Hi all,
Is there plan to implement
yield
keyword in Espruino?Motivation
Main purpose is to be able to translate such a simple Python code:
do_something() while True: x = do_something_else() if x == 0: break sleep(0.1) # wait 100ms do_another_thing()
into this form (in Livescript):
do-something! while true break if do-something-else! is 0 yield new Promise -> set-timeout it, 100 do-another-thing!
or in Javascript:
doSomething(); for (;;) { if (doSomethingElse() === 0) { break; } (yield new Promise(fn$)); } doAnotherThing(); function fn$(it){ return setTimeout(it, 100); }
as we discussed in this Livescript thread. There are two things come into play: Promises, which you seem to discussed earlier and the
yield
keyword....or is there any external library/technique to achieve something similar?
-
Hi,
Sorry for the late reply, we have been dealing with a CAN bus issue.
I generally examplify "learning a programming language" with "using a rent car", or "taking a bus". You might feel yourself comfortable in your car (or some models of buses) but if you need to travel to meet with your friends, it wasn't be a problem the type of vehicle you use; you would just use it to reach the target. That's such a kind of thing to me.
-
Smalltalk was in my TODO list (my list of languages to be learned) along with Elixir, Lua and Lisp =)
Our learning survey is mainly motivated by our commercial applications' needs (we learn whatever we need to, or invent sometimes). For example I was forced to learn Python in order to program a Telit 863-PY GSM module, then I liked it very much =)
-
Thank you all for everything, the problem has been solved. Here are the results:
configFile = null; configInit = function(){ if (configFile === null) { configFile = getFile(); } }; configWrite = function(index, value){ configInit(); configFile.write(index, value); }; configRead = function(index){ configInit(); return E.toString(configFile.read(index)); };
Usage:
>configWrite(0, "hello") =undefined >configWrite(1, "world") =undefined >configRead(0) ="hello" >configRead(1) ="world" >
-
-
-
@allObjects Thank you, here I could achieve the solution:
# create bundle BUNDLE="init.min.js" echo "" > ${BUNDLE} # Register modules via `Modules.addCached()` method # see: http://forum.espruino.com/comments/12899741/ MODULE_NAME="FlashEEPROM" MODULE_STR=$(uglifyjs -c -m -- ${MODULE_NAME}.js | sed 's/\"/\\\"/g' | sed "s/\n//g") echo "Modules.addCached(\"${MODULE_NAME}\", \"${MODULE_STR}\");" >> ${BUNDLE} uglifyjs -c -m -- init.js >> ${BUNDLE}
Now I can
require("FlashEEPROM")
as expected. -
It seems a little bit diverged, but not at all: Could you please take a look at this problem because I guess this is the only problem left. If I can make a bundle by myself, I can use
FlashEEPROM
module.PS: I'm dealing with this problem since I'm not able to use EspruinoWebIDE right now.
-
@Gordon Now I understand better. I'm still trying to understand the working mechanism of Espruino, but clearly I didn't yet.
The fact is, I'm not using the Web IDE. I have built a toolset (and will publish when ready for daily usage) where the main purpose is to use Livescript transparently. So I may manually download FlashEEPROM module.
-
@Wilberforce I need to store ESSID and password except from default ones. I will hardcode a default ESSID+password and save an additional one. If new ESSID+password fails long enough, I will fallback to the default one. That's why I need some other place to store these values.
Anyway, there is only
Flash
module seems to work. I'll follow this document and write some simple driver functions. I'll get back to you. -
I am totally sure that I tried above
...require("FlashEEPROM")...
code a few hours ago and it returned an object, but now it fails with following error message:_____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v85 Copyright 2016 G.Williams Espruino is Open Source. Our work is supported only by sales of official boards and donations: http://espruino.com/Donate Flash map 512KB:256/256, manuf 0xe0 chip 0x4014 >require("FlashEEPROM") WARNING: Module "FlashEEPROM" not found =undefined >
I guess no, since
sleep
(issetTimeout
under the hood) scheduleslo(op)
call and previous execution oflo(op)
ends there. Which means there is nothing related withlo(op)
function's execution within this 5ms duration.