• If I use inline c to compile a function, and then I attach it to to say, the NFCon, NFCoff, and NFCrx callbacks, what would happen?

    Would the callback see that it's a native function and execute it directly, or would it jump into the javascript interpreter just to jump back into the native code?

    In my experience with inlineC, the time required to call it from javascript is more than the time to execute it, so it's faster to just keep everything in javascript, but if inlineC attached to a native callback stays native, well...

    If this isn't an allowed behavior, maybe it wouldn't be a terrible idea to have a way to attach native c functions to callbacks directly that don't jump out to the javascript interpreter for at least some of the more time sensitive ones (like NFC)

    also, is it possible to output to the console from inline c at all?

  • Would the callback see that it's a native function and execute it directly, or would it jump into the javascript interpreter just to jump back into the native code?

    It is not clear what exactly you consider to be javascript interpreter vs native code as whole interpreter is native code but if you specifically mean parsing javascript source and interpreting it then there is no such thing if no source is involved. So if the callback is native method there is no javascript source to parse and interpret.

    In my experience with inlineC, the time required to call it from javascript is more than the time to execute it, so it's faster to just keep everything in javascript

    I fail to see the logic in the conclusion you made. Interpreting is slow so yes, it is slower (when compared to native code) before it gets to the point where it runs your native method and then it is slower again when it leaves it but the sum of total time is still smaller than having it all in javascript. There is no extra slowdown caused by calling native method compared to calling javascript method so you can only gain speed by using it.

    even smallest simplest native method gives speed boost, try e.g. uploading this

    var c = E.compiledC(`
    // int add(int, int)
    int add(int x,int y){
    return x+y;
    }
    `);
    function jsadd(x,y){return x+y;}
    
    function run(f){
    var x,y;
    for (y=0;y<64;y++) {
     for (x=0;x<64;x++) f(x,y);
    }
    }
    

    and then measure the difference of using add vs jsadd method

    >var d=Date();run(jsadd);d=Date().ms-d.ms;pri­nt("jsadd "+d);
    jsadd 2362.36572265625
    =undefined
    >var d=Date();run(c.add);d=Date().ms-d.ms;pri­nt("add "+d);
    add 1586.57836914062
    

    So just replacing method call of doing x+y in javascript loop saved you 800ms which is more than 1/3 of total time!

    also, is it possible to output to the console from inline c at all?

    Not easily. accessing any javascript variable (like console) and calling into it from native inline c code is tricky. In theory everything what can be done from "compiled" javascript code (see https://www.espruino.com/Compilation) should be possible in inline c code (so also calling methods of objects) but it won't be pretty.

  • Hi! In some cases, inline c can be called a bit more 'directly' - eg setWatch(..., {irq:true}).

    However for NFC and Bluetooth stuff it's not really possible - they are designed around a message queue, which pushes data from interrupt-land down to the message loop. By the time you're in the message loop and have seen that you're calling inline c, it's too late.

    Judging by your other posts about NFC/Inline C, I think you're at the point where you really want to be looking at compiling your own firmware to implement what you want - it's really not hard at all.

    is it possible to output to the console from inline c at all?

    In theory, yes. You have access to these functions: https://github.com/gfwilliams/EspruinoCo­mpiler/blob/master/src/utils.js#L74

    So you could do something like:

    var c = E.compiledC(`
    // int test(int)
    int test(int n){
      JsVar *p = jspGetNamedVariable("print");
      JsVar *s = jsvNewFromString("Hello world");
      jsvUnLock(jspeFunctionCall(p,0,0,false,1­,&s));
      jsvUnLock(s);
      jsvUnLock(p);
    }
    `);
    
    c.test(20);
    // prints 'Hello World'
    

    In a way it might be nice to have a bit of a standard library of functions (eg digitaWrite/etc) that can be called from Inline C

  • Hi! In some cases, inline c can be called a bit more 'directly' - eg setWatch(..., {irq:true}).

    However for NFC and Bluetooth stuff it's not really possible - they are designed around a message queue, which pushes data from interrupt-land down to the message loop. By the time you're in the message loop and have seen that you're calling inline c, it's too late.

    Would it be at all possible to call NRF.nfcSend or the native equivalent function from compiledC?

    I could be wrong, but it seems if hal_nfc_send, and hal_nfc_send_rsp were exported for web compilation that it could work purely from C without even another command once it jumps back to javascript

    I hope I'm not being too annoying with all these questions... just trying to figure out a way to write a fast script that doesn't require a custom firmware

    In a way it might be nice to have a bit of a standard library of functions (eg digitaWrite/etc) that can be called from Inline C

    Yes it would be...

  • it seems if hal_nfc_send, and hal_nfc_send_rsp were exported for web compilation

    Yes, that would work. OR if you know the firmware version you're using then you could figure out the address of hal_nfc_send and just include it directly in your code.

    However, as I'd said above, having the faster function won't help you, since the compiled function will be called like a normal JS function - from the event loop rather than as an interrupt.

    Are you trying to do something extremely special, or do you just want to emulate the standard NFC tag format that we currently do, but with the ability to write data?

    If it's the latter I think it makes sense for me to just add the functionality inside core Espruino

  • I’m trying to write an NFC emulator that conforms to the NTAG215 spec and can do read / write, a “magic ntag” if you will.

    Functionality similar to what the chameleon mini provides.

    The issue doesn't seem to be entirely so much the time it takes to get to the event loop and execute the code, but rather the time it takes the code to execute.

    I’ve implemented a good portion of the spec in pure JavaScript but the more checks I add the less likely it is to successfully scan, this is why I want to get as native and as fast as possible without having to keep iterating with native firmware and re-flashing the whole shebang over Bluetooth (I don't have a debugger for one...)

    I’ve done some testing and built a custom firmware with those hal function pointers exposed and I was then able to write some inlineC code that can be called by passing it the pointer and length of the rx buffer, then I respond directly from native code, it works but it weirdly is less compatible than the same logic in pure JavaScript... is there more overhead to get the pointer and jump to the compiled inlineC function than there is to just keep it all in javascript?

  • is there more overhead to get the pointer and jump to the compiled inlineC function than there is to just keep it all in javascript?

    That's odd. Not at all - inline C should be fast to execute.

    is there any specific reason certain functions like malloc, calloc, and free aren't exposed to inlineC?

    They don't exist in Espruino :) It allocates everything in the JsVars area - if needed you could do the same using the functions that are exposed though.

  • Well, to get around malloc I just allocate a buffer from javascript and use a native setter function to set the pointer, so that's not a huge issue, memcpy I just re-implement, but that could probably be passed like the other functions that are in the firmware.

    Maybe it would be possible to set up the NFC interrupt so that it can execute native functions by their pointer that are assigned by NRF.on("nfcRx", myNativeFunction) if they match a certain signature?

    That could also be applied to any event handler really, but I haven't run into any timing-critical ones other than NFC.

    It's not so much that implementation of NFC protocols can't be done with inlineC, but more so that going through the event loop just adds a delay that causes issues, especially if you just end up calling a native method anyways.

    I know that the hardware is capable of it, there are different projects doing this with native firmware.

    It could certainly be a module implemented in the firmware, but for my specific purpose I want to add support for non-standard NFC commands for my own use... things like being able to rewrite the entire tag payload, change to different payloads entirely and such over NFC using a custom app... I use bluetooth right now to take care of that, but nfc rx/tx is so much faster.

    I'll try exposing all of the hal nfc method pointers so I can use them with inlineC and just make use of those directly... yes, I know at that point I should just make a native firmware or bake it into the espruino firmware, but even if debugging is limited it's still easier to iterate using the web ide for me at least anyways.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Question about assigning compiled inline c functions to callbacks

Posted by Avatar for DanTheMan827 @DanTheMan827

Actions