SPI Flash mit Frimware beschreiben

Hallo zusammen,
ich habe folgende Herausforderung: ich habe das hier Compact, $25 spectrometer | Hackaday.io gefunden und gleich eines gekauft: https://www.tindie.com/products/onehorse/compact-as7265x-spectrometer/. Funktioniert einwandfrei, passt aber nicht ganz zu meinen Steckverbindern. Also hab ich mir eine entsprechend angepasste Platine gemacht und vom freundlichen Musterprogramm bei ams profitiert, die gerne mal Bauteile zu Testzwecken rausrücken.
Leider habe ich nicht die ganze Litanei auf Hackaday gelesen. Insbesondere den Teil, in dem die Firmware des Sensors auf den Flashchip gespielt wird, habe ich übersehen: Successfully Loaded Firmware, First Test of Design | Details | Hackaday.io. Heute saß ich dann recht ratlos da. Denn leider ist der Arduinosketch, der den Flash bespielen würde, wohl recht massgeschneidert auf das Dragonflyboard, das der Entwickler verwendet hat:

/* loadSPIFlash_AS7265X_Dragonfly.ino
 *  
Sketch by Kris Winer January 14, 2018

License: Use this sketch any way you choose; if you like it, buy me a beer sometime

Purpose: Reads 16 MByte SPI NOR flash on LoRa SensorTile and reconstructs bytes into 
spreadsheet-readable scaled sensor data

Sketch takes advantage of the SPI.beginTransaction/SPI.EndTransaction protocol for efficiency
and maximum speed.

Sketch based on the work of Pete (El Supremo) as follows:
 * Copyright (c) 2014, Pete (El Supremo), el_supremo@shaw.ca
 *
 * Development of this audio library was funded by PJRC.COM, LLC by sales of
 * Teensy and Audio Adaptor boards.  Please support PJRC's efforts to develop
 * open source software by purchasing Teensy or other PJRC products.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice, development funding notice, and this permission
 * notice shall be included in all copies or substantial portions of the Software.
 */

#include <SPI.h>
#include "FS.h"
#include "SPIFlash.h"

// Highest page number is 0xFFFF = 65535 for 128 Mbit flash
// Highest page number is 0x7FFF = 32767 for  64 Mbit flash
// Highest page number is 0x0FFF =  4095 for   8 Mbit flash
// Highest page number is 0x07FF =  2047 for   4 Mbit flash
uint16_t max_page_number = 0x07FF;
unsigned char flashPage[256];
unsigned char r_page[256];
uint16_t page_number = 0, numbytes = 0;

#define csPin 10
#define myLed 26

SPIFlash SPIFlash(csPin);

File file;

void setup(void)
{ 
  DOSFS.begin();
  delay(1000);

  file = DOSFS.open("/AS7265.2.fw", "r"); 

  // Set up LED pin
  pinMode (myLed, OUTPUT);
  digitalWrite(myLed, HIGH);
  delay(100);
 
  Serial.begin(115200);
  delay(4000);
  Serial.println("Serial enabled!");

  if(file)
  {
    Serial.println("File Open!");
  } 
  else
  {
    Serial.println("File Open Failed!");
    while(1) { };
  }

  pinMode(csPin, OUTPUT);
  digitalWrite(csPin, HIGH);

  // check SPI Flash ID
  SPIFlash.SPIFlashinit();
  SPIFlash.powerUp();
  SPIFlash.getChipID();

  SPIFlash.flash_chip_erase(true); // erase the SPI flash before writing firmware
  delay(100);
  

  for (page_number = 0; page_number < 2048; page_number++)
  {
  numbytes = file.read(flashPage, 256); // 256 bytes per page, 2047 pages
  Serial.print("first two bytes: "); Serial.print("0x"); Serial.print(flashPage[0], HEX); Serial.print("  0x"); Serial.println(flashPage[1], HEX);
  Serial.print("Number of bytes = "); Serial.println(numbytes);  // print number of bytes read

  SPIFlash.flash_page_program(flashPage, page_number);
  Serial.print("Wrote flash page: "); Serial.println(page_number);
  digitalWrite(myLed, LOW); delay(1); digitalWrite(myLed, HIGH); // indicate when flash page is written
  }

  
  // read AS7265X SPI flash
  for(page_number = 0; page_number < 2048; page_number++)  
  {

  //  Serial.print("Read Page 0x"); Serial.println(page_number, HEX);
  SPIFlash.flash_read_pages(r_page, page_number, 1);
      
  for(uint16_t i = 0; i < 256; i++) 
  {
  Serial.print(" 0x"); Serial.print(r_page[i], HEX);
  if (i % 16==0) Serial.println();
  }
  
  Serial.println("");
  }

}

void loop(void)
{
}

Er kompiliert nur fehlerfrei, wenn man das Dragonflyboard installiert und auswählt, sonst stören sich alle boards am "DOSFS". Das alles übersteigt leider meine Programmierfähigkeiten.
Daher nun meine Frage: wie kriege ich die Firmware auf den Flashchip? Ich muss vielleicht gleich dazu sagen, dass die FW-Datei 256 kB groß ist und also nicht irgendwie mit in einen sketch gepackt und im setup einmalig auf den Flash geschrieben werden kann (höchstens mit dem Due, oder einem Teensy?). Oder? Oder gibt es ein Programm und einen sketch, die zusammen arbeiten, um eine FW-Datei über USB an einen Arduino zu schicken, damit der sie per SPI weiter auf den Flash schiebt?
Ich fände es schön, wenn mir jemand weiterhilft und ich mein Verständnis vertiefen kann. Und mir 50 € und die Warterei sparen könnte, bis ein Dragonflyboard hier ist. Ich habe die Arduino IDE 1.8.8, einen Teensy 3.2, diverse Arduinos (und Levelshifter) und ESP8266-boards. Als Flashchip habe ich den adesto AT25SF041 eingebaut, der im Datenblatt des AS7265X als Möglichkeit aufgeführt ist. Mehr Code und Infos gibts hier GitHub - kriswiner/AS7265X: 18-channel, 40-nm FWHM spectrometer, aber Vorsicht, das Datenblatt ist veraltet, ich hänge ein neueres an. Sollte jemand Lust bekommen, habe ich das eine oder andere Platinchen übrig.
Vielen Dank im voraus. Seid bitte gnädig ob meines Unwissens, ich weiß selber, dass ich nichts weiß.

AS7265x_DS000612_1-00.pdf (1.03 MB)

Hast Du die Lib FS.h installiert? Kannst Du uns da mal einen Link dazu geben?

Gruß Tommy

Meine Vermutung ist, das das File, was in den SPI Flash soll, im Flash des Boardes, was den Chip flashen soll, Platz haben muß. Die gängigen Arduinoboards haben dafür zu wenig Flash.

Tommy56:
Hast Du die Lib FS.h installiert? Kannst Du uns da mal einen Link dazu geben?

Gruß Tommy

Hallo Tommy56,
die FS.h ist im ESP8266 Paket drin, daher musste ich sie nicht installieren. Ist im Anhang.

@ nix_mehr_frei: ja, nomen est omen, so hab ich das auch verstanden.

Danke schonmal.

FS.cpp (6.69 KB)

FS.h (3.32 KB)

Du hast nirgends geschrieben, dass Du das mit einem ESP8266 lösen willst. Das ist kein Arduino. Dort wird eigentlich eher SPIFFS benutzt.

Bist Du Dir sicher, dass das Board ein ESP8266 ist?

Kann es sein, dass Du da etwas falsch verstanden hast?

Gruß Tommy

Also die möglichkeit wäre nur Versuchsweise mit dem ESP8266..

Das klappt schon.. Du musst die firmwaredatei mit dem Namen in das Spiff hochladen (Schonmal gemacht?).

und nur 1-2 Zeilen ändern.

Zum Beispiel:

#include <SPI.h>
#include "FS.h"
#include "SPIFlash.h"

// Highest page number is 0xFFFF = 65535 for 128 Mbit flash
// Highest page number is 0x7FFF = 32767 for  64 Mbit flash
// Highest page number is 0x0FFF =  4095 for   8 Mbit flash
// Highest page number is 0x07FF =  2047 for   4 Mbit flash
uint16_t max_page_number = 0x07FF;
unsigned char flashPage[256];
unsigned char r_page[256];
uint16_t page_number = 0, numbytes = 0;

#define csPin 10
#define myLed 26

SPIFlash SPIFlash(csPin);

File file;

void setup(void)
{
  //DOSFS.begin();
  delay(1000);

  file = SPIFFS.open("/AS7265.2.fw", "r");

  // Set up LED pin
  pinMode (myLed, OUTPUT);
  digitalWrite(myLed, HIGH);
  delay(100);
 
  Serial.begin(115200);
  delay(4000);
  Serial.println("Serial enabled!");

  if(file)
  {
    Serial.println("File Open!");
  }
  else
  {
    Serial.println("File Open Failed!");
    while(1) { };
  }

  pinMode(csPin, OUTPUT);
  digitalWrite(csPin, HIGH);

  // check SPI Flash ID
  SPIFlash.SPIFlashinit();
  SPIFlash.powerUp();
  SPIFlash.getChipID();

 SPIFlash.flash_chip_erase(true); // erase the SPI flash before writing firmware
  delay(100);
 

  for (page_number = 0; page_number < 2048; page_number++)
  {
  numbytes = file.read(flashPage, 256); // 256 bytes per page, 2047 pages
  Serial.print("first two bytes: "); Serial.print("0x"); Serial.print(flashPage[0], HEX); Serial.print("  0x"); Serial.println(flashPage[1], HEX);
  Serial.print("Number of bytes = "); Serial.println(numbytes);  // print number of bytes read

  //SPIFlash.flash_page_program(flashPage, page_number);
  Serial.print("Wrote flash page: "); Serial.println(page_number);
  digitalWrite(myLed, LOW); delay(1); digitalWrite(myLed, HIGH); // indicate when flash page is written
  }

 
  // read AS7265X SPI flash
  for(page_number = 0; page_number < 2048; page_number++) 
  {

    Serial.print("Read Page 0x"); Serial.println(page_number, HEX);
 SPIFlash.flash_read_pages(r_page, page_number, 1);
     
  for(uint16_t i = 0; i < 256; i++)
  {
  Serial.print(" 0x"); Serial.print(r_page[i], HEX);
  if (i % 16==0) Serial.println();
  }
 
  Serial.println("");
  }

}
void loop(){}

Tommy56:
Du hast nirgends geschrieben, dass Du das mit einem ESP8266 lösen willst. Das ist kein Arduino. Dort wird eigentlich eher SPIFFS benutzt.

Bist Du Dir sicher, dass das Board ein ESP8266 ist?

Kann es sein, dass Du da etwas falsch verstanden hast?

Gruß Tommy

Hallo Tommy,
nun ja, wollen wollte ich nicht, aber da es nun mal nicht mit einem Mega geht...
Dass die FS.h im ESP8266-Paket steckt, habe ich auch nur so zufällig in irgendeinem Forum gefunden. Sie hat mir irgendwie gar nicht gefehlt.
Ich glaube, ich hab den generellen workflow schon richtig verstanden.
@Schuppeste: Spiffs? Oje. Aber vielen Dank, das ist ja mal ein Anfang. Ich werde mal versuchen, mich durchzubeissen und mich ggf. wieder melden.

Aber dann fehlt ihm in den Quellen immer noch DOSFS. Das klingt nicht nach SPIFFS, eher nach SD.

Gruß Tommy

Tommy56:
Aber dann fehlt ihm in den Quellen immer noch DOSFS. Das klingt nicht nach SPIFFS, eher nach SD.
Gruß Tommy

Nein.. DOSFS ist ja eine File Quelle wie SPIFF.. die Bytes der Firmware bleiben ja gleich ob nun aus DOSFS oder SPIFF geladen.

diese habe ich in meinem Codebeispiel auf SPIFF geändert.

@godo

Du benötigst nur den ESP8266 Data Uploader und musst den Flash an die ESP8266 SPI Pins anschliessen. ob die SPIFLASH Lib beim ESP8266 standard ist weiß ich jetzt nicht.

Den ESP8266 data Uploader nach Anleitung installieren, im Ordner des Sketches einen "data" Ordner anlegen und dort die Firmware Datei hinkopieren.

Ich war mal in der gleichen Situation und habe Arduino-Serprog mit flashrom genutzt.
https://www.flashrom.org/Serprog/Arduino_flasher

Der Data-Uploader ist grottenlahm, weil er immer das ganze SPIFFS schreibt.

Bessere Varianten sind der SPIFFS-Uploader von mir oder weiter ausgebaut der von Fips.

Gruß Tommy

Tommy56:
Der Data-Uploader ist grottenlahm, weil er immer das ganze SPIFFS schreibt.

Danke, schau ich mir mal an.. Ich benutze Spiff eher seltener und kann mit dem kompletten Upload leben.

Mache das spiff meistens sowieso voll :smiley:

Wenn Du aber nur mal eine Datei austauschen/löschen/hinzufügen willst, ist der Zeitunterschied extrem.

Gruß Tommy

Hallo,
ich habe vermutlich erfolgreich die Datein in den SPIFF meines NodeMCU 1.0 geladen. Dazu habe ich den Data Uploader installiert wie hier beschrieben: https://www.instructables.com/id/Using-ESP8266-SPIFFS/. Danach habe ich bemerkt, dass ich keinen Sketch mehr auf ESP-boards laden kann, weder auf den Node, noch auf Wemos D1 oder D1mini. Auch ein Entfernen des Data Uploader Ordners aus dem Toolsordner und eine Regression auf IDE 1.8.1 hat bisher nix genützt. Nicht ESP-Boards kompilieren, aber ansonsten gibt es folgende Fehlermeldung:

(...)
"C:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\2.5.0-3-20ed2b9/bin/xtensa-lx106-elf-g++" -D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-IC:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2/tools/sdk/include" "-IC:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2/tools/sdk/lwip2/include" "-IC:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2/tools/sdk/libc/xtensa-lx106-elf/include" "-IC:\Users\SEBAST~1\AppData\Local\Temp\arduino_build_810594/core" -c -Wall -Wextra -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections -fexceptions -DF_CPU=80000000L -DLWIP_OPEN_SRC -DTCP_MSS=536 -DLWIP_FEATURES=1 -DLWIP_IPV6=0   -DARDUINO=10801 -DARDUINO_ESP8266_NODEMCU -DARDUINO_ARCH_ESP8266 -DARDUINO_BOARD="ESP8266_NODEMCU"   -DESP8266 "-IC:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\cores\esp8266" "-IC:\Users\Sebastian\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0-beta2\variants\nodemcu" "C:\Users\SEBAST~1\AppData\Local\Temp\arduino_build_810594\sketch\Blink.ino.cpp" -o "C:\Users\SEBAST~1\AppData\Local\Temp\arduino_build_810594\sketch\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
cmd.exe /c rem cannot sign on windows
exec: "cmd.exe": executable file not found in %PATH%
Fehler beim Kompilieren für das Board NodeMCU 1.0 (ESP-12E Module).

Ich habe zwar beim Googeln nach "exec: "cmd.exe": executable file not found in %PATH%" einiges gefunden, aber nix, was mir geholfen hätte. Irgendwelche Ideen? Danke!

ich glaube nich das die Fehlermeldung irgendwas mit den data sachen zu tun hat.. da ist was anderes nicht okay.

Ja, das fürchte ich auch. Ich Deinstalliere nochmal die IDE, räume die Registry auf und fege die AppData durch. Dann nochmal alles schrittweise neu installieren...

Gut, der Fehler ist weg und ich kann wieder kompilieren. Die Kombination aus IDE 1.8.8 und ESP8266 vers 2.4.2 funktioniert, mit der aktuellen 2.5er, die nach der Neuinstallation verwendet wurde, gings nicht. Weiter gehts...

Ich benutze überigens so einen Programmer mit flashprog, das geht ganz gut mit Linux.. müsste auch in Windows klappen. (habe für die Käfer ICS eine passende Klemmzange)