Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XMC flash support - WIP #6725

Merged
merged 21 commits into from
Apr 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6634415
Move the spi vendor list from Esp.h to its own header in eboot.
ChocolateFrogsNuts Nov 8, 2019
46578fe
Fix ifdef issue with spi_vendors.h
ChocolateFrogsNuts Nov 8, 2019
d49a4ec
Add initFlashQuirks() for any chip specific flash initialization.
ChocolateFrogsNuts Nov 8, 2019
55c23cf
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Nov 8, 2019
fc5013f
namespace experimental for initFlashQuirks()
ChocolateFrogsNuts Nov 9, 2019
f6e2559
Merge branch 'master' into xmc_flash
devyte Nov 14, 2019
c63da34
Merge branch 'master' into xmc_flash
devyte Nov 15, 2019
b4e5e78
Merge branch 'master' into xmc_flash
devyte Nov 19, 2019
4dc15ea
Slow down flash access during eboot firmware copy
ChocolateFrogsNuts Nov 21, 2019
cb3ab4a
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Nov 21, 2019
7491779
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Nov 22, 2019
61c0a33
Slow down flash access during eboot firmware copy on XMC chips
ChocolateFrogsNuts Nov 22, 2019
3229f3d
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Nov 22, 2019
814bb0d
Merge branch 'xmc_flash' of https://github.com/ChocolateFrogsNuts/Ard…
ChocolateFrogsNuts Nov 22, 2019
da39eb9
Merge branch 'master' into xmc_flash
earlephilhower Dec 21, 2019
ebb1bce
Merge branch 'master' into xmc_flash
devyte Apr 20, 2020
3ff5ec5
Commit eboot.elf
ChocolateFrogsNuts Apr 23, 2020
be68c14
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Apr 23, 2020
a19ea69
Commit eboot.elf
ChocolateFrogsNuts Apr 23, 2020
aa4a711
Merge branch 'master' into xmc_flash
ChocolateFrogsNuts Apr 23, 2020
7dd4738
Merge branch 'xmc_flash' of https://github.com/ChocolateFrogsNuts/Ard…
ChocolateFrogsNuts Apr 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions bootloaders/eboot/eboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <string.h>
#include "flash.h"
#include "eboot_command.h"
#include "spi_vendors.h"
#include <uzlib.h>

extern unsigned char _gzip_dict;
Expand Down Expand Up @@ -189,6 +190,28 @@ int copy_raw(const uint32_t src_addr,
return 0;
}

#define XMC_SUPPORT
#ifdef XMC_SUPPORT
// Define a few SPI0 registers we need access to
#define ESP8266_REG(addr) *((volatile uint32_t *)(0x60000000+(addr)))
#define SPI0CMD ESP8266_REG(0x200)
#define SPI0CLK ESP8266_REG(0x218)
#define SPI0C ESP8266_REG(0x208)
#define SPI0W0 ESP8266_REG(0x240)

#define SPICMDRDID (1 << 28)

/* spi_flash_get_id()
Returns the flash chip ID - same as the SDK function.
We need our own version as the SDK isn't available here.
*/
uint32_t __attribute__((noinline)) spi_flash_get_id() {
SPI0W0=0;
SPI0CMD=SPICMDRDID;
while (SPI0CMD) {}
return SPI0W0;
}
#endif // XMC_SUPPORT

int main()
{
Expand All @@ -211,9 +234,48 @@ int main()

if (cmd.action == ACTION_COPY_RAW) {
ets_putc('c'); ets_putc('p'); ets_putc(':');

#ifdef XMC_SUPPORT
// save the flash access speed registers
uint32_t spi0clk = SPI0CLK;
uint32_t spi0c = SPI0C;

uint32_t vendor = spi_flash_get_id() & 0x000000ff;
if (vendor == SPI_FLASH_VENDOR_XMC) {
uint32_t flashinfo=0;
if (SPIRead(0, &flashinfo, 4)) {
// failed to read the configured flash speed.
// Do not change anything,
} else {
// select an appropriate flash speed
// Register values are those used by ROM
switch ((flashinfo >> 24) & 0x0f) {
case 0x0: // 40MHz, slow to 20
case 0x1: // 26MHz, slow to 20
SPI0CLK = 0x00003043;
SPI0C = 0x00EAA313;
break;
case 0x2: // 20MHz, no change
break;
case 0xf: // 80MHz, slow to 26
SPI0CLK = 0x00002002;
SPI0C = 0x00EAA202;
break;
default:
break;
}
}
}
#endif // XMC_SUPPORT
ets_wdt_disable();
res = copy_raw(cmd.args[0], cmd.args[1], cmd.args[2]);
ets_wdt_enable();

#ifdef XMC_SUPPORT
// restore the saved flash access speed registers
SPI0CLK = spi0clk;
SPI0C = spi0c;
#endif
ets_putc('0'+res); ets_putc('\n');
if (res == 0) {
cmd.action = ACTION_LOAD_APP;
Expand Down
Binary file modified bootloaders/eboot/eboot.elf
Binary file not shown.
63 changes: 63 additions & 0 deletions bootloaders/eboot/spi_vendors.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
spi_vendors.h - Vendor IDs for SPI chips
Copyright (c) 2019 Mike Nix. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef __SPI_VENDORS_H__
#define __SPI_VENDORS_H__

// Vendor IDs taken from Flashrom project
// https://review.coreboot.org/cgit/flashrom.git/tree/flashchips.h?h=1.0.x
// Moved here from ../../cores/esp8266/Esp.h
typedef enum {
SPI_FLASH_VENDOR_ALLIANCE = 0x52, /* Alliance Semiconductor */
SPI_FLASH_VENDOR_AMD = 0x01, /* AMD */
SPI_FLASH_VENDOR_AMIC = 0x37, /* AMIC */
SPI_FLASH_VENDOR_ATMEL = 0x1F, /* Atmel (now used by Adesto) */
SPI_FLASH_VENDOR_BRIGHT = 0xAD, /* Bright Microelectronics */
SPI_FLASH_VENDOR_CATALYST = 0x31, /* Catalyst */
SPI_FLASH_VENDOR_EON = 0x1C, /* EON Silicon Devices, missing 0x7F prefix */
SPI_FLASH_VENDOR_ESMT = 0x8C, /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */
SPI_FLASH_VENDOR_EXCEL = 0x4A, /* ESI, missing 0x7F prefix */
SPI_FLASH_VENDOR_FIDELIX = 0xF8, /* Fidelix */
SPI_FLASH_VENDOR_FUJITSU = 0x04, /* Fujitsu */
SPI_FLASH_VENDOR_GIGADEVICE = 0xC8, /* GigaDevice */
SPI_FLASH_VENDOR_HYUNDAI = 0xAD, /* Hyundai */
SPI_FLASH_VENDOR_INTEL = 0x89, /* Intel */
SPI_FLASH_VENDOR_ISSI = 0xD5, /* ISSI Integrated Silicon Solutions, see also PMC. */
SPI_FLASH_VENDOR_MACRONIX = 0xC2, /* Macronix (MX) */
SPI_FLASH_VENDOR_NANTRONICS = 0xD5, /* Nantronics, missing prefix */
SPI_FLASH_VENDOR_PMC = 0x9D, /* PMC, missing 0x7F prefix */
SPI_FLASH_VENDOR_PUYA = 0x85, /* Puya semiconductor (shanghai) co. ltd */
SPI_FLASH_VENDOR_SANYO = 0x62, /* Sanyo */
SPI_FLASH_VENDOR_SHARP = 0xB0, /* Sharp */
SPI_FLASH_VENDOR_SPANSION = 0x01, /* Spansion, same ID as AMD */
SPI_FLASH_VENDOR_SST = 0xBF, /* SST */
SPI_FLASH_VENDOR_ST = 0x20, /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */
SPI_FLASH_VENDOR_SYNCMOS_MVC = 0x40, /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */
SPI_FLASH_VENDOR_TENX = 0x5E, /* Tenx Technologies */
SPI_FLASH_VENDOR_TI = 0x97, /* Texas Instruments */
SPI_FLASH_VENDOR_TI_OLD = 0x01, /* TI chips from last century */
SPI_FLASH_VENDOR_WINBOND = 0xDA, /* Winbond */
SPI_FLASH_VENDOR_WINBOND_NEX = 0xEF, /* Winbond (ex Nexcom) serial flashes */
SPI_FLASH_VENDOR_XMC = 0x20, /* Wuhan Xinxin Semiconductor Manufacturing Corp */

SPI_FLASH_VENDOR_UNKNOWN = 0xFF
} SPI_FLASH_VENDOR_t;

#endif // __SPI_VENDORS_H__
6 changes: 6 additions & 0 deletions cores/esp8266/Esp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ uint32_t EspClass::getFlashChipSizeByChipId(void) {
return (64_kB);

// Winbond
case 0x1840EF: // W25Q128
return (16_MB);
case 0x1640EF: // W25Q32
return (4_MB);
case 0x1540EF: // W25Q16
Expand All @@ -423,6 +425,10 @@ uint32_t EspClass::getFlashChipSizeByChipId(void) {
case 0x1340E0: // BG25Q40
return (512_kB);

// XMC - Wuhan Xinxin Semiconductor Manufacturing Corp
case 0x164020: // XM25QH32B
return (4_MB);

default:
return 0;
}
Expand Down
38 changes: 1 addition & 37 deletions cores/esp8266/Esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,7 @@
#define ESP_H

#include <Arduino.h>

// Vendor IDs taken from Flashrom project
// https://review.coreboot.org/cgit/flashrom.git/tree/flashchips.h?h=1.0.x
typedef enum {
SPI_FLASH_VENDOR_ALLIANCE = 0x52, /* Alliance Semiconductor */
SPI_FLASH_VENDOR_AMD = 0x01, /* AMD */
SPI_FLASH_VENDOR_AMIC = 0x37, /* AMIC */
SPI_FLASH_VENDOR_ATMEL = 0x1F, /* Atmel (now used by Adesto) */
SPI_FLASH_VENDOR_BRIGHT = 0xAD, /* Bright Microelectronics */
SPI_FLASH_VENDOR_CATALYST = 0x31, /* Catalyst */
SPI_FLASH_VENDOR_EON = 0x1C, /* EON Silicon Devices, missing 0x7F prefix */
SPI_FLASH_VENDOR_ESMT = 0x8C, /* Elite Semiconductor Memory Technology (ESMT) / EFST Elite Flash Storage */
SPI_FLASH_VENDOR_EXCEL = 0x4A, /* ESI, missing 0x7F prefix */
SPI_FLASH_VENDOR_FIDELIX = 0xF8, /* Fidelix */
SPI_FLASH_VENDOR_FUJITSU = 0x04, /* Fujitsu */
SPI_FLASH_VENDOR_GIGADEVICE = 0xC8, /* GigaDevice */
SPI_FLASH_VENDOR_HYUNDAI = 0xAD, /* Hyundai */
SPI_FLASH_VENDOR_INTEL = 0x89, /* Intel */
SPI_FLASH_VENDOR_ISSI = 0xD5, /* ISSI Integrated Silicon Solutions, see also PMC. */
SPI_FLASH_VENDOR_MACRONIX = 0xC2, /* Macronix (MX) */
SPI_FLASH_VENDOR_NANTRONICS = 0xD5, /* Nantronics, missing prefix */
SPI_FLASH_VENDOR_PMC = 0x9D, /* PMC, missing 0x7F prefix */
SPI_FLASH_VENDOR_PUYA = 0x85, /* Puya semiconductor (shanghai) co. ltd */
SPI_FLASH_VENDOR_SANYO = 0x62, /* Sanyo */
SPI_FLASH_VENDOR_SHARP = 0xB0, /* Sharp */
SPI_FLASH_VENDOR_SPANSION = 0x01, /* Spansion, same ID as AMD */
SPI_FLASH_VENDOR_SST = 0xBF, /* SST */
SPI_FLASH_VENDOR_ST = 0x20, /* ST / SGS/Thomson / Numonyx (later acquired by Micron) */
SPI_FLASH_VENDOR_SYNCMOS_MVC = 0x40, /* SyncMOS (SM) and Mosel Vitelic Corporation (MVC) */
SPI_FLASH_VENDOR_TENX = 0x5E, /* Tenx Technologies */
SPI_FLASH_VENDOR_TI = 0x97, /* Texas Instruments */
SPI_FLASH_VENDOR_TI_OLD = 0x01, /* TI chips from last century */
SPI_FLASH_VENDOR_WINBOND = 0xDA, /* Winbond */
SPI_FLASH_VENDOR_WINBOND_NEX = 0xEF, /* Winbond (ex Nexcom) serial flashes */

SPI_FLASH_VENDOR_UNKNOWN = 0xFF
} SPI_FLASH_VENDOR_t;
#include "spi_vendors.h"

/**
* AVR macros for WDT managment
Expand Down
85 changes: 85 additions & 0 deletions cores/esp8266/core_esp8266_flash_quirks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
flash_quirks.cpp - Chip specific flash init
Copyright (c) 2019 Mike Nix. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include <c_types.h>
#include "spi_flash.h"

#include "spi_utils.h"
#include "flash_quirks.h"

#ifdef __cplusplus
extern "C" {
#endif

namespace experimental {

static int get_flash_mhz() {
// FIXME: copied from Esp.cpp - we really should define the magic values
uint32_t data;
uint8_t * bytes = (uint8_t *) &data;
// read first 4 byte (magic byte + flash config)
if(spi_flash_read(0x0000, &data, 4) == SPI_FLASH_RESULT_OK) {
switch (bytes[3] & 0x0F) {
case 0x0: // 40 MHz
return 40;
case 0x1: // 26 MHz
return 26;
case 0x2: // 20 MHz
return 20;
case 0xf: // 80 MHz
return 80;
default: // fail?
return 0;
}
}
return 0;
}

/* initFlashQuirks()
* Do any chip-specific initialization to improve performance and reliability.
*/
void initFlashQuirks() {
using namespace experimental;
uint32_t vendor = spi_flash_get_id() & 0x000000ff;

switch (vendor) {
case SPI_FLASH_VENDOR_XMC:
uint32_t SR3, newSR3;
if (SPI0Command(SPI_FLASH_CMD_RSR3, &SR3, 0, 8)==SPI_RESULT_OK) { // read SR3
newSR3=SR3;
if (get_flash_mhz()>26) { // >26Mhz?
// Set the output drive to 100%
newSR3 &= ~(SPI_FLASH_SR3_XMC_DRV_MASK << SPI_FLASH_SR3_XMC_DRV_S);
newSR3 |= (SPI_FLASH_SR3_XMC_DRV_100 << SPI_FLASH_SR3_XMC_DRV_S);
}
if (newSR3 != SR3) { // only write if changed
if (SPI0Command(SPI_FLASH_CMD_WEVSR,NULL,0,0)==SPI_RESULT_OK) // write enable volatile SR
SPI0Command(SPI_FLASH_CMD_WSR3,&newSR3,8,0); // write to SR3
SPI0Command(SPI_FLASH_CMD_WRDI,NULL,0,0); // write disable - probably not needed
}
}
}
}

} // namespace experimental

#ifdef __cplusplus
}
#endif
3 changes: 3 additions & 0 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
}
#include <core_version.h>
#include "gdb_hooks.h"
#include "flash_quirks.h"

#define LOOP_TASK_PRIORITY 1
#define LOOP_QUEUE_SIZE 1
Expand Down Expand Up @@ -334,6 +335,8 @@ extern "C" void user_init(void) {

initVariant();

experimental::initFlashQuirks(); // Chip specific flash init.

cont_init(g_pcont);

preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
Expand Down
42 changes: 42 additions & 0 deletions cores/esp8266/flash_quirks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
flash_quirks.h
Copyright (c) 2019 Mike Nix. All rights reserved.
This file is part of the esp8266 core for Arduino environment.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef FLASH_QUIRKS_H
#define FLASH_QUIRKS_H

#ifdef __cplusplus
extern "C" {
#endif

#include "spi_vendors.h"
#include "spi_flash_defs.h"

namespace experimental {

void initFlashQuirks();

} // namespace experimental

#ifdef __cplusplus
}
#endif


#endif // FLASH_QUIRKS_H
Loading