OTA through Ethernet with Teensy 4.1

AndyA, are you saying that including flasherX in my code should be enough to meet this check?
Well that didn't seem to work for me. I had to use it somewhere in the code before it would work.
Although that makes sense I'll check it again.
 
You shouldn't need to manually include it. I never did. For the code to check whether a string is there it needs to include that string so it knowns what to look for. It's a self fulfilling requirement which does make it a very smart way to implement a basic sanity check that code has been built for the correct target before installing it.
I'm not sure why it didn't work for you, I suppose the compiler could have been too clever when it comes to optimising things but it does seem odd.

If you do need to manually include something then rather than having a Serial.print("fw_teensy41"); in your code I'd recommend using Serial.print(FLASH_ID); that way you'll always include the correct string that it is looking for based on the device you're compiling for.
 
I'm working on using this flasherX to remote update over Ethernet. I got the transfer of the hex file to the teensy4.1 working, but I not sure how to get the lines of hex into the buffer. Does the (flash_write_block) keep track of the address to write the lines to or do I need to do that?
I looked at the async web server example but I dont want to use that code in the final write.
Thought about saving the hex lines to the sd card and them using the sd example in flasherX to finish.
Any Ideas?
 
The buffer must contain the binary image, not the hex lines. Since the hex lines are being sent via Ethernet, you can either convert to binary as the packets are received, similar to receiving via UART, or you can write the hex lines to SD and then read the file and convert to binary. Either one will work. I don't know how the async web server works, so I don't know whether one would be simpler/easier. If the async web server directly supports file transfer, then it would probably be easier to think of the process as transferring the hex file to SD, then updating from SD.
 
Define a variable to track the hex decode status
C:
hex_info_t hex = {
    // intel hex info struct
    data, 0, 0, 0,     //   data,addr,num,code
    0, 0xFFFFFFFF, 0,  //   base,min,max,
    0, 0               //   eof,lines
  };

Once you have received the HEX file data in a loop split the received hex data into text lines based on 0x0a or 0x0d characters
Filter out any lines with 0 length
Then call function below with a pointer to the start of each line in turn.
If it returns false at any point abort the upgrade.
C:
bool processHexLine(const char* line) {
  if (parse_hex_line(line, hex.data, &hex.addr, &hex.num, &hex.code) == 0) {
    Serial.printf("abort - bad hex line %s\n", line);
    return false;
   } else if (process_hex_record(&hex) != 0) {  // error on bad hex code
     Serial.printf("abort - invalid hex code %d\n", hex.code);
    return false;
   } else if (hex.code == 0) {  // if data record decoded OK
      uint32_t addr = buffer_addr + hex.base + hex.addr - FLASH_BASE_ADDR;
      if (hex.max > (FLASH_BASE_ADDR + buffer_size)) {
        Serial.printf("abort - max address %08lX too large\n", hex.max);
        return false;
      } else if (!IN_FLASH(buffer_addr)) { // copy to buffer in ram
        memcpy((void*)addr, (void*)hex.data, hex.num);
      } else if (IN_FLASH(buffer_addr)) {  // copy to buffer in flash
        int error = flash_write_block(addr, hex.data, hex.num);
        if (error) {
          Serial.printf("abort - error %02X in flash_write_block()\n", error);
          return false;
        }
      }
    }
    hex.lines++;
  }
  return true;
}

Once whole input has been processed you will have the binary firmware image in the flasherX buffer.
You can then run a basic check on it and if that passes install it using flash_move.
C:
if (check_flash_id(buffer_addr, hex.max - hex.min))
    flash_move(FLASH_BASE_ADDR, buffer_addr, hex.max - hex.min);

In addition to the flashID check that flasherX uses I also run my own sanity check that the image has the correct header.
This is teensy4 / 4.1 only:
C:
bool VerifyValidImage(uint8_t *imageStart) {
  uint32_t SPIFlashConfigMagicWord = *((uint32_t*)imageStart);
  uint32_t VectorTableMagicWord = *((uint32_t*)(imageStart+0x1000));
  if ((SPIFlashConfigMagicWord == 0x42464346) && (VectorTableMagicWord==0x432000D1)) {
    uint32_t imageEntryPoint = *((uint32_t*)(imageStart+0x1004));
    if ((imageEntryPoint < (FLASH_BASE_ADDR+0x1000)) || (imageEntryPoint > (FLASH_BASE_ADDR+0x2000))) {
      Serial.printf("Image indicates a code entry point at 0x%08X, this is outside the expected range.\r\n", imageEntryPoint);
      return false;
    }
    Serial.printf("Image indicates a code entry point at 0x%08X.\r\n",imageEntryPoint);
    return true;
  }
  Serial.printf("Image doesn't have expected ivt table magic number\r\n");
  return false;
}


With the exception of the extra verification step this is essentially the process both the web version and the SD card file reading are doing, the only difference is where they get the hex file from. In your case it will be a buffer in memory that was populated with data from a network socket.
 
Thanks AndyA, question the hex.data, &hex.addr, &hex.num, &hex.code are not declared, nor are process_hex_record, parse_hex_line
what library am I missing that these come from?
 
As @joepasquariello indicated they are from flasherX

I moved the lines
Code:
typedef struct {  
  char* data;         // pointer to array allocated elsewhere
  unsigned int addr;  // address in intel hex record
  unsigned int code;  // intel hex record type (0=data, etc.)
  unsigned int num;   // number of data bytes in intel hex record

  uint32_t base;  // base address to be added to intel hex 16-bit addr
  uint32_t min;   // min address in hex file
  uint32_t max;   // max address in hex file

  int eof;    // set true on intel hex EOF (code = 1)
  int lines;  // number of hex records received
} hex_info_t;
int parse_hex_line(const char* theline, char* bytes, unsigned int* addr, unsigned int* num, unsigned int* code);

Into fxutil.h and then #included that in my code.
hex is then a variable of type hex_info_t.
Sorry I'd forgotten I'd made that change.
 
Back
Top