-
Howdy Ducky,
Have a look at the following and see if this helps ...https://github.com/espruino/Espruino/blob/master/targets/esp8266/docs/05-User_Guide.md
If that doesn't completely answer your questions, PLEASE post back so that we can address by making those docs clearer.
-
I am not seeing any obvious modification needed to the library as is .... here is my thinking. SPI hardware support is indeed a lot of register poking. Quite a bit of it in fact. The complexity of decoding the registers and making the correct sequence of register pokes is complex. This library has done the hard work of that. It exposes "high level" APIs for driving hardware SPI. For example, it has an API to set the clock speed, it has an API to send/receive bits and to specify the bit length ... and it has an API to determine if an SPI request is currently in progress.
By treating these capabilities as "black box" then the jsSPISend and related Espruino interfaces become controllers for the black-box capability of the MetalPhreak library.
If my thinking is sound, then the ESP8266 SPI hardware library would be leveraged "as-is" without any modification upon it. So ... there will be jshardware changes needed ... but these will drive MetalPhreak without ever having to "look inside" the register poking complexities.
Is this your thinking too?
-
Ive put out a call for community involvement here ... http://www.esp8266.com/viewtopic.php?f=9&t=6376 ... to see if there are some practices that might be shared on how to move strings out of RAM assuming it is possible.
-
-
-
What should our policy and practices be on using non-original code within Espruino? For example, there appears to be an excellent candidate source code library that provides hardware SPI for ESP8266 ... see:
https://github.com/MetalPhreak/ESP8266_SPI_Driver
What should we do if Espruino would like to include that within a board? Do we have precedent for using other libraries? Should we contact the authors and ask for permission? Do we have a "credits" page associated with Espruino where these authors can get the notifications that their licenses may require?
-
I built a new set of firmware using the latest code base ... attached is the new trace and memory usage. It looks like the changes made by @Gordon seem to have saved 180 blocks.
Will upload a new binary/firmware set for the ESP8266 now.
As for the "missing" 17K ... ...
After booting with Espruino - free heap = ~5K
Known JsVars = 1024*x 16 = ~16K
Total known = 16K + 5K = ~21K
ESP8266 Booted with no firmware but WiFi and TCP = ~40K
Un-accounted for RAM = 40K - 21K = ~19KMy first impression is ... and this is a guess ... that String constants are placed in RAM. So if in C we code:
char *x = "hello";
or
if (strcmp(x, "hello")) ...
Then the string constants eat RAM. I am "guessing" that some large portion of the missing RAM is used by strings.
For example, I looked at
jsinteractive.o
uses 2100 bytes andjsparse.o
uses 1900 bytes and there are likely other hitters out there too. I don't know enough to know if static character string can be moved to flash or instruction RAM but I'm going to guess not. -
@DrAzzy ... There is an open issue on hardware support for the ESP8266 SPI which is Issue #606 ... https://github.com/espruino/Espruino/issues/606
There are a bunch of links from there to the available docs and other forum entries. From what I can tell, it appears that one can use a hardware SPI for I/O driving without it affecting the operation of flash ... however, I for one, have not been able to comprehend the documentation to figure out a design that would allow us to include the hardware SPI support in Espruino. This is one of those areas where I had been hoping to engage an SPI skilled ESP8266 resource ... or at the very least, find others who would be willing to collaborate on bit-by-bit comprehension of the story.
-
I loaded just the MQTT.js file and seem to find that has used about 900 blocks of JsVar. I have attached the file showing the trace. I am not good at reading these but I seem to be seeing that the majority of blocks (that I can see) are used to hold JavaScript text ...
The source file of MQTT.js is about 8K.
The amount of RAM in the ESP8266s today is very low. At best, with absolutely nothing but WiFi and TCP loaded, Espressif tell us that we can use about 40K. If we then subtract from that 1024 JsVars ... I think that takes us down to about 28K. I think when Espruino boots from fresh on an ESP8266, the heap left is about 9K and from that, the TCP/IP memory buffers need to be allocated. However there appears to be about 17K un-accounted for that is probably worthy of short term investigation.
My hope though is that within 6 months (maybe more, maybe less) the RAM available will increase by a 10x factor and hopefully that will push the problem to the far right.
-
Do you have any ideas for new projects? How are the boys over at smart.js (https://smartjs.io/) funding their projects?
It seems to me (as an outsider in the IoT world) that there are many burgeoning companies that are setting themselves up as IoT and Cloud based technologies. While I personally "like" tinkering with home automation thingies ... I suspect that the winner will be some industry broad standard with which "appliances" will embrace and come pre-shipped/enabled ... as opposed to smart plugs and the like.
From where I sit, I'm not sure that a revenue stream on Espruino boards is going to necessarily grow into the future. I base that on the notion that the cost of boards is tumbling and the availability of environments for programmers to write code upon is increasing. Combine that with the moore's law of technology increase and "secret sauce" of an embedded custom written JavaScript may be displaced by "commodity" JavaScript runtimes once the base board has RAM and CPU to accommodate. For example, in my Java world, the latest Java 8 has a first class JavaScript engine built into the JAVA JVM ... so one can write JavaScript AND Java running on a JVM ... and since those JVMs are being ported all over the place ... it drags a common JavaScript environment with it.
In my work life, I tend to think about what can I do to delight customers NEXT ... so the challenge is always to look ahead 6 months, 1 year and 5 years and attempt to predict what they might want based upon all the input I hear. Many times though I don't LIKE what I hear because it is divergent from what we thought the direction was going to be or our competition are stronger in those areas. It is then that we have to be smarter and go to more heroic lengths ... and sometimes that takes us in directions we hadn't anticipated.
At those times, I get a large cup of coffee and re-read "Who moved my cheese?".
-
-
A NeoPixel also known as the WS2812 has an ultra specific set of timing criteria ... see for example:
https://www.adafruit.com/datasheets/WS2812.pdf
We need a signal length of 0.35us to represent low and 0.7us to represent high. These have tolerances of +/- 150ns. The overall period of 1 bit is about 1.3us. As such, timing is absolutely critical. The AdaFruit sample code for an ESP8266 can be found here which uses assembly to access the ESP8266 special register called "ccount" which uses the 80MHz/160MHz clock cycle counter for this level of precision:
https://github.com/adafruit/Adafruit_NeoPixel/blob/master/esp8266.c
The equivalent Adruino code seems to be mostly written in assembler ... see:
https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
Using these as references, we see both an API and an implementation that has been demonstrated to work. If it is possible to drive reliable signals at these rates using SPI, I'm afraid I personally don't know how to do that. We are also stuck on hardware SPI support on the ESP8266 and that has been an outstanding issue for a while now with no obvious resolution.
If we can achieve NeoPixel driving with hardware SPI, that would be fantastic ... but in the interim, this story talks about a potential code fragment that works today using the recipes that others (Adafruit) are advocating ... as opposed to SPI techniques. If it is possible to drive NeoPixels using hardware SPI on an ESP8266, that may indeed be a breakthrough that even folks like AdaFruit would be interested in hearing about.
-
I think we probably don't want to miss the wood for the trees. The reason that there is a current usefulness for native code in C/Assembler for NeoPixels is because they have sub microsecond timing requirements that can't be done at the JavaScript level. To the best of my limited knowledge, this appears to be the only example of such a story. If it is a very rare boundary case ... then I'd hate for us to set up an infrastructure for custom builds and there be no other value or need beyond NeoPixels.
If a contributor to Espruino internals development has an hour to spare ... would we want that hour spent on custom code inclusion or would we prefer that the hour be spent burning down the open Issues that already exist?
The NeoPixels story came up because there was an apparent "usage pattern" being asked for by user after user. However, I'm not hearing of other stories that seem to "require" native code (C/Assembler) support.
-
The good news is that I have mechanically tested calling NeoPixels from JS using a combination of C and assembler as the driver and it seems to work great. Using JS as the driver means I can write net code and use JS as the driver for the pixels.
However, until and unless we reach consensus on whether or not to include it in the ESP8266 base distribution, I'll leave it out of the GIT repository.
-
While working on the ESP8266 port of Espruino, we came across requests for driving WS2811, WS2812 and other NeoPixel devices. Unfortunately, hardware ESP8266 support for SPI or I2C isn't there yet. However, others in un-related ESP8266 projects have pioneered correct driving of NeoPixels using C and Assembler. These code snippets can easily be incorporated into Espruino builds as new modules. For example:
var neopixel = require("NeoPixel"); // This is made up and not real.... don't try it neopixel.write(D1, [r1, g1, b1, r2, g2, b2, ...]);
However, just because we can do something ... never means we should. Now we have a community and project owner question. What should we do about the (hopefully few) modules that need to be implemented in the Espruino base code in C?
These are the choices I see:
1) We bake it into Espruino ... it is just "there" for folks to use ... it increases the firmware size by an amount but we live with it. (I think the WS2812 code came out to be an increase of about 150-200 bytes).
2) We don't bake it into Espruino ... but leave it in the "source" such that a custom build could be attempted by those who wish to make a custom build containing the code.
3) As (2) but multiple firmware builds are distributed for each release ... some with features and some without.
4) We don't accommodate function into Espruino that isn't "obviously" going to be used by the vast majority of Espruino users.
Let's open this up for discussion and see what we, as a community, think and can come up with. Maybe there are other ideas or solutions? However, lets be practical ... ideas such as "Let us create a build server where a custom Espruino build can be generated on demand based upon a user's selection" sure sounds awesome ... but multiply the number of boards and environments ... and monies ... that might be needed for that ... it isn't likely to fly ... and ... if it did, chances are we would have to fall back to one of the simpler ideas so that function could be delivered before such a "build machine" became practical and then we might be back at the start again.
Besides NeoPixel support, what have others heard of that might require "native C" support within Espruino?
-
This is great info ... it is demonstrating that I don't understand JsVars anywhere near as well as I thought I did.
What is the algorithm on "UnLock"? Is it a counter? Is it a boolean? If it is a counter, is it considered "freed" if the count reaches zero?
A discussion on JsVar usage would make a great session for board contributors.
-
I am wondering if there was a reason that
jsvUnLock()
does not return the JsVar that it is unlocking?If it did, it would seem to offer me a new way of coding. For example, today I have the option of coding:
JsVar *x = jsvNewFromInteger(10); jsvUnLock(x);
while if jsvUnLock() returned its passed in JsVar, then I would appear to have the option:
JsVar *x = jsvUnLock(jsvNewFromInteger(10));
-
I am examining the nature of the problems I personally introduce into the code base and I find that too many of them relate to failure to jsvUnLock created JsVar instances. Is there a technique that others use to diagnose such leaks? Ideally, I'd like to see a list of JsVars with their times of creation and their times of last access. I'm pretty sure that data isn't available in a JsVar object but maybe in a debug build such a thing might be useful.
-
I only have opinion on the ESP8266 board. My vote is one board for the ESP8266. This would encompass ESP-01, ESP-12, NodeMCU devKit and boards from Adafruit, Sparkfun and all the others out there. While I fully realize that some of these boards expose lesser pins on the physical board, in each case, they are all ESP8266s. When writing a JavaScript app for any and all of these boards, the app will be the same. Obviously a programmer running the script on an ESP-01 will have less physical pins to solder against ... but the program will still run without error ... they just have to be cognizant that they can't easily get to the additional pins for electrical connection.
The amount of flash memory does indeed differ by board. However ... if the Espruino code base will fit within the minimum flash (512K) that we have so far seen with an ESP8266 I am wondering if there isn't a run-time solution to determine (or configure) the flash size available to applications? If there were, this would then allow us to have one set of firmware for ALL ESP8266 boards irrespective of flash size.
The objection I anticipate to that last notion is that it will prevent Over The Air (OTA) flashing of new Espruino firmware builds to an ESP8266. While loss of any function is lamentable, my vote on that issue is that OTA for Espruino is a low priority item. Once we hit stability of ESP8266 port, I do not anticipate refreshes of the Espuino firmware at a rate that would result in gross dissatisfaction with USB->UART loading.
-
I'm trying to imagine Espruino in a year or 2 years or 5 years. In projects that I am involved in ... in real-life ... we have fallen into the trap of "it works just fine now, why change anything" ... and the competition comes along and increments their functional base inch by inch ... a year later we look around and all of a sudden the customer base is saying "Why don't you do this ... and this ... and this ..." and by then its too late .. our competition has done all of that already.
We should assume that by this time next year or 2 years or 5 years ... the capabilities of the base MCUs will be dramatically better than we have today. If we don't plan to take advantage of those platforms, we will be caught short when the capability becomes actual.
This does bring up the concept though of strategic direction. Is Espruino focused exclusively at the low end MCU into the future? If it wants to remain at the low-end with the belief that the Linux eco system will prevail with its spectrum of development tools for higher end MCUs ... then yes ... maintenance mode of Espruino is probably sufficient.
-
-
Howdy @allObjects, I'm afraid I'm not 100% with you. This is a rather subtle area and requires a deep context for conversation. It juggles HTTP protocol, TCP/IP parlance (sockets), and the design of the 'http' module in Espruino and specifically subtleties in HTTP headers related to "Connection".
I'll be delighted to have a conversation with you on these topics but am not sure a forum post back and forth is the best way to go. If you want to go that route, keep posting and I'll keep responding. If you prefer, we can chat publicly or privately on the gitter stream. If you wish, we can also chat actually via skype ... I am always keen to find folks who wish to understand the internals of areas that I am tinkering with ... so that we may share our thinking and considerations. I find that a puzzle shared is usually a puzzle halved.
The source for the Espruino networking areas are:
libs/network/jswrap_net.c
libs/network/network.c
libs/network/socketserver.c
libs/network/http/jswrap_http.cand then the board specific networking files.
-
@Gordon I am also working the story from the perspective of the recipient of the HTTP Request ... in this case the AutoRemote application for Android. It is worth reviewing the logs and story that I have pasted there:
http://forum.joaoapps.com/index.php?threads/tcp-or-rest-protocol-for-receiving-commands.1569/
My best guess right now is that there are two errors in play ... and again ... this is a guess. One side comes from Espruino and one side comes from AutoRemote. Here is my thinking.
1) Espruino sends a GET HTTP request to AutoRemote ... which responds with an HTTP Response but does NOT close the HTTP connection. Even though the response message has returned "Content-Length" bytes, Espruino has not closed the connection and hence no 'on(close)' callback. This may be working as implemented but it might not be working as fully desired. As a JS programmer, I now don't have a nice mechanism to know when I have received a "unit" of HTTP response even though the knowledge is present. I.e. the header of the response says the body is "XYZ" bytes long and after having received "XYZ" bytes ... there is no callback to say that the "unit" of response is present.
2) AutoRemote is not honoring the "Connection: close" request sent by Espruino which "should" close the connection after sending a single response back. However ... even though that is likely wrong of AutoRemote and I'm taking that up with the AutoRemote team, I'm not convinced that Espruino shouldn't handle this story as part of a "keep-alive" strategy.
Howdy Ducky ... this warning can be found as a tracked issue here:
https://github.com/espruino/Espruino/issues/675
Thankfully the warning can be "ignored" and all should function. This one needs @Gordon to look into it as it appears to relate to files managed by the Web Server located at "espruino.com". My loose understanding is that when we use the Web IDE and execute a "require" then that causes a REST request to be made from the IDE back to "espruino.com" which, loosely, says "I would like a copy of the JavaScript corresponding to that named module". I believe that the REST request also includes the type of board you are using so that if there is board specific code, that can be matched correctly. Since the board you are using is an "ESP8266" and, currently, the web site doesn't know what that is ... you get a warning message. However, since the module is actually "built-in" to the ESP8266 firmware, all still works as there was nothing to be downloaded in the first place.