• I hope this it the correct place to post this..

    I'm trying to create a CAN Bus lib and I'm running Espruino on a Nucleo STM32F4 board. I'm not great with C but I can usually make my way around, but I've been just looking at other libs to try to figure this out.

    I'm running out of memory (I think) and the runtime crashes. I wrote a nodejs app to blast data (a frame every 2ms) to the Nucleo. When I use jsiConsolePrintf to dump the CAN frame out to the console it works without issue, so this tells me the Interrupt code is fine. But I want to dispatch an event into the JS runtime so that the frame data can be used there. When I do this the chip crashes after just a few minutes.

    Here is how I am dispatching the event:

      * @brief  Read CAN FIFO and dispatch JS event with the CAN Message data
      * @param  None
      * @retval None
    void CANx_ReadAndDispatch(CAN_TypeDef *CANx, uint8_t FIFONumber){
      CanRxMsg RxMessage;
      CAN_Receive(CANx, FIFONumber, &RxMessage);
      // Dispatch event
      JsVar *messageObj = messageObjectFromRxStruct(&RxMessage);
        jsiQueueObjectCallbacks(jsVarCan1, JS_EVENT_PREFIX"message", &messageObj, 1);
    *   Build a JS Object from the CAN RX data
    JsVar *messageObjectFromRxStruct(CanRxMsg *rx){
      uint32_t *id;
      // uint8_t size = rx->DLC+2;
      uint8_t size = 11;
      char dest[size];
      if(rx->IDE == CAN_ID_EXT)
        id = &rx->ExtId;
        id = &rx->StdId;
      // memset(dest, '\0', size);
      dest[0] = (*id >> 8);
      dest[1] = (*id);
      dest[10] = rx->DLC;
      strncpy(dest+2, rx->Data, 8);
      // Mem check
      if (jsuGetFreeStack() < 88) {
        jsExceptionHere(JSET_ERROR, "CAN:: Not enough free stack to receive this mesage. stackfree:%d", jsuGetFreeStack());
        return 0;
      JsVar *buffer = jsvNewArrayBufferWithData(11, dest);
      return buffer;
  • What you're doing looks ok - but you're doing this from an interrupt?

    It's likely that what is happening is Espruino does something like a garbage collection pass outside of an interrupt (very occasionally), but then if your interrupt happens while that is running, it may not be able to get data reliably and so might break.

    Usually that's ok (apart from lost data), but if you're printing data at a high IRQ level and then the output buffer gets full, you can get deadlocked.

    If you're on the Nucleo then I guess you could run a debugger and find out what/where the error occurred.

    However when implementing Bluetooth I decided a while back that allocating JS variables in interrupts just wasn't working reliably. Especially as it looks like you're only sending chunks of 11 bytes I'd just define a static buffer, write the data to that in an IRQ, and then handle that in an 'idle' handler.

    ... or Bluetooth support actually writes data into the input buffer (eg. https://github.com/espruino/Espruino/blo­b/master/targets/nrf5x/bluetooth.c#L211) but I think that's overkill for what you want here.

  • Great! I was assuming the jsvUnlock method is similar to Objective-C retain/release mechanism so I wanted to make sure all the espruino js methods were being used correctly.

    Glad you mentioned the buffer thing, that was my next move. Setup a test and it seems to be working really well. I didn't realize the idle method was a good place to do some processing, I was thinking it was to allow sleep or something along those lines. Good to know!

    Now I can do some cleanup and more testing. Looking forward to picking up some official hardware like the Puck so that I can get it working on there also.

    Thanks for your help and awesome product Gordon!

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

Running out of memory building a library in C (on Nucleo board)

Posted by Avatar for user63214 @user63214