Need help with writing to FLASH problem

Post Reply
PhilHaw
Posts: 65
Joined: Thu Mar 07, 2019 5:37 pm

Need help with writing to FLASH problem

Post by PhilHaw »

During a Firmware update of our new pedal, we have a routine to flash the updated DSP programs to FX Core Flash memory. The problem I'm seeing is that, after all the programs are written to flash, which works correctly, there is no sound until I manually reset the FX Core Dev board by momentarily grounding the RST pin. I suspect the FX Core is not returning to the Run state.

When testing I replace the WRITE_PRG command with an EXEC_FROM_RAM and this works correctly. As you can see from the code fragment below, the routine pauses after each program is sent to the FX Core and I can play test it before hitting a button to go on to the next program. After the last program the FX Core does return to the Run state, and I can hear the program that is currently selected on the 'Program Select' switch on the Dev Board.

Code: Select all

void programAllFlash() {

  //  readFXCoreStatus();
  // Calculate the number of FXCore programs in the code arrays
  uint8_t DSPprograms = sizeof(prgSize) / sizeof(prgSize[0]);

  tft.fillScreen(BLACK);
  tft.setTextSize(2);
  for (uint8_t i = 0; i < DSPprograms; i++) {
    tft.setCursor(0, 120);
    tft.print("Flashing Program ");
    tft.print(i);
    flashProgram(i, i);  // Here we call the flashProgram() function for each of our programs in the FXCPrograms.h file
    delay(10);
  }

  // Refresh the display
  displayPatchNumber(PATCHFONT, CYAN);
  displayPatchName(isUserPatch, BIGFONT, CYAN);
  displayProgamName(isUserPatch);
  displayKnobLabels(ThisPatch.FXCoreProgram);
  clearLeftOfCentreLine();
  displayHeads();
  for (int p = 0; p < NUMPOTS; p++) {
    displayAnalogValue(BIGFONT, KNOB_NORMAL_COLOR, p * knobSpacing, ThisPatch.param[p + 1]);
  }
}

// Write the given program to the specified FXCore Flash Memory
// unit8_t program = DSP program number (0-15)
// unit8_t location = FXCore Flash memory location to program (0-15)
void flashProgram(uint8_t program, uint8_t location) {

// Comment out the next line to test in RAM rather than writing to FLASH
  #define WRITE_FLASH

  EnterPRGmode();  // Tell the FXCore to get ready to receive a program
  delay(10);       // Allow the FXCore a little time to be ready

  // Send the registers
  sendCREGS(cregList[program]);
  sendMREGS(mregList[program]);
  sendSFR(sfrList[program]);

  // Send the program data to the FXCore (RAM)
  sendPROG(prgList[program], (prgSize[program] - 2) / 4);
  delay(10);

#ifndef WRITE_FLASH
  // For testing just execute the program from RAM
  ExecuteFromRAM();
  delay(10);
  boolean UPpressed = false;
  boolean DOWNpressed = false;

  while (!UPpressed && !DOWNpressed) {
    UPpressed = !digitalRead(UPSW_PIN);
    DOWNpressed = !digitalRead(DOWNSW_PIN);
  }

#else
  //  Tell the FXCore to write the program to the specified FLASH location
  writeProg(location);
  delay(10);
#endif

  ReturnFXCoreToState0();
  ExitProgram();
}
If I take a look at the diagnostic printout, I can see that when running the EXEC_FROM_RAM option, the FXCore returns 0 after each command, which obviously means 'success'. On the other hand, when the WRITE_PRG is active, the FXCore is returning 0 after the program is sent but it's returning '2' after the RETURN_0 and EXIT_PRG commands.

Any idea what I am doing wrong?
When testing with EXEC_FROM_RAM

12:27:44.111 -> sendPROG - Number of FXCore instructions: 70
12:27:44.149 -> Sent EXEC_FROM_RAM cmd: FX Core returned: OK
12:27:47.850 -> Sent RETURN_0 cmd: FX Core returned: 0
12:27:47.850 -> Sent EXIT_PRG cmd: FX Core returned: 0
12:27:47.991 -> sendPROG - Number of FXCore instructions: 91
12:27:48.037 -> Sent EXEC_FROM_RAM cmd: FX Core returned: OK
12:27:50.490 -> Sent RETURN_0 cmd: FX Core returned: 0
12:27:50.490 -> Sent EXIT_PRG cmd: FX Core returned: 0

When writing to FLASH location

12:32:53.819 -> sendPROG - Number of FXCore instructions: 70
12:32:53.866 -> Write to location 11 command sent. FXCore returned: 0x0
12:32:53.866 -> Sent RETURN_0 cmd: FX Core returned: 2
12:32:53.866 -> Sent EXIT_PRG cmd: FX Core returned: 2
12:32:54.005 -> sendPROG - Number of FXCore instructions: 91
12:32:54.037 -> Write to location 12 command sent. FXCore returned: 0x0
12:32:54.084 -> Sent RETURN_0 cmd: FX Core returned: 2
12:32:54.084 -> Sent EXIT_PRG cmd: FX Core returned: 2
Philip Hawthorne

Blue Nebula Development Team
Frank
Posts: 159
Joined: Sun May 03, 2015 2:43 pm

Re: Need help with writing to FLASH problem

Post by Frank »

Hard so see why as there are so many possible things. Do you have a logic analyzer and able to capture the SDA and SCL lines? We use Saleae devices here so if you have one capture the complete transaction and send us the capture file so we can open it in their s/w. If not a Saleae then use what you have and let us know what it is so we can see if we can find a viewer.

I am unsure what you mean by "FX Core returned: 2" as the FXCore can only send a status word if requested and I did not see that in the code. Otherwise on the I2C line it can ACK or NACK so if you are using an I2C library it may be returning the "2" as an error of some form.

I would increase the delay after sending the write program command, the flash can be a little slow to write to. In the assembler I wait 200mS after a write command, longer than necessary but not an issue as it is still very fast from a user perspective.

Also get and print the status word after each command (each transfer, the write, etc.) so we can see what the FXCore thinks is going on.

Also I think the chip returns to state 0 after a write program command so you may not need that, try removing the RETURN_0 after the "Write to location"
DisasterArea
Posts: 26
Joined: Sat Jul 25, 2020 7:07 pm

Re: Need help with writing to FLASH problem

Post by DisasterArea »

Here's how I do it:

Send an I2C command: Address 0x30, 0xA5, 0x5A, 0x30

This puts the FXCore in program mode

Send MREGs: 0x30, 0x04, 0x7F, mreg_data

Send CREGs: 0x30, 0x01, 0x0F, creg_data

Send SFRs: 0x30, 0x02, 0x0B, sfr_data

Send PRG: 0x30, progSize >> 8, progSize & 0x00FF
Send PRG data: 0x30, prg_data

Now the FXCore should have all the data it needs but it'll be sitting there doing nothing.

If you want to run from RAM, send 0x30, 0x0D, 0x00.
To exit run from RAM mode, send 0x30, 0x0E, 0x00 to return to state 0, then send 0x30, 0x5A, 0xA5 to exit program mode and run.

If you want to program to a slot, send 0x30, 0x0C, slot_number
Then send 0x30, 0x5A, 0xA5 (this is backwards from the "enter" command) to exit program mode and run.

Frank's point about a delay between commands is 100%. I would recommend you put at least a 20ms delay between writes, 100ms won't hurt or even be noticeable to the user.
PhilHaw
Posts: 65
Joined: Thu Mar 07, 2019 5:37 pm

Re: Need help with writing to FLASH problem

Post by PhilHaw »

Thanks to both of you for your helpful suggestions.

@Frank: I removed the RETURN_0 after the write command but it didn't help. You're correct about the 'error' value, It's being returned from the I2C library and it corresponds to a 'NACK (Address)' error.

@DisasterArea: As far as I can tell, I'm doing exactly the same as you. I will try using some longer delays as you and Frank have suggested.

I do have a Salae Logic 8 so if the longer delays don't fix the problem I will get it fired up and sniff the I2C transaction.

Phil.
Philip Hawthorne

Blue Nebula Development Team
PhilHaw
Posts: 65
Joined: Thu Mar 07, 2019 5:37 pm

Re: Need help with writing to FLASH problem

Post by PhilHaw »

Yes! Adding a 200ms delay after the WRITE_PRG command did the trick. I also removed the RETURN_0 command but that was not necessary as it now works either with or without it.

My guess is that, without sufficient delay after the write command, the FXCore is still writing the data to flash when the EXIT_PRG command comes so it misses it and the I2C library gets a 'NACK' from the bus.

Thank you so much guys for your help!

Phil.
Philip Hawthorne

Blue Nebula Development Team
Frank
Posts: 159
Joined: Sun May 03, 2015 2:43 pm

Re: Need help with writing to FLASH problem

Post by Frank »

PhilHaw wrote: Tue Oct 18, 2022 9:36 am My guess is that, without sufficient delay after the write command, the FXCore is still writing the data to flash when the EXIT_PRG command comes so it misses it and the I2C library gets a 'NACK' from the bus.
That is exactly what happens, when we are writing the flash everything else is ignored so we don't screw up the flash.

I should add a note on delaying after the write command to the app note.

EDIT: Updated PDF to add delay after WRITE_PRG in the "Typical Steps to Program a Location"
Post Reply